【问题标题】:Applying JsonDictionary attribute to dictionary将 JsonDictionary 属性应用于字典
【发布时间】:2017-03-30 15:45:21
【问题描述】:

如果我尝试将 JsonDictionary 属性添加到 .net Dictionary(Of Integer, MyClass),编译器会告诉我,无法应用该属性。这是为什么呢?

<JsonDictionary()>
Public ReadOnly Property monatswerte As Dictionary(Of Integer, MyClass)

我基本上找不到任何在线使用JsonDictionary的例子。

【问题讨论】:

  • 我没用过,所以帮不上忙,但是source code[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)],所以只能在类或接口上使用。如果(像我一样)您不知道如何使用它,也许这不是您正在寻找的答案 - 也许您应该询问您正在尝试解决的问题? :-)
  • 我添加了.netc# 标签,因为问题和答案不是特定语言的。

标签: c# .net vb.net json.net


【解决方案1】:

&lt;JsonDictionary()&gt; 可以应用于类型(类或接口)以强制 Json.NET 的 default contract resolver(及其子类)为该类型生成 dictionary contract。它是三个相似属性家族的一部分:

  • &lt;JsonObject()&gt;。强制将类型序列化为 JSON 对象。用于强制序列化集合属性而不是项目,如 here 所示。
  • &lt;JsonArray()&gt;。强制将类型序列化为 JSON 数组。可能有用,例如,强制将字典序列化为键/值对数组。
  • &lt;JsonDictionary()&gt;。强制将类型解释为字典并序列化为 JSON 对象。 (当然,它仍然必须实现 IDictionaryIDictionary&lt;TKey, TValue&gt; 才能工作。)

从表面上看,&lt;JsonDictionary()&gt; 似乎没有那么有用,因为DefaultContractResolver.CreateContract(Type objectType) 在检查任何其他接口实现之前检查传入类型是否实现IDictionary。但是,该属性有几个properties,它们可能有助于自定义字典的序列化方式,包括:

  • NamingStrategyTypeNamingStrategyParameters 允许控制字典keys 的大小写和名称映射。

    例如,即使CamelCasePropertyNamesContractResolver 正在使用,以下字典将始终按字面意思序列化其键,而不重命名:

    <JsonDictionary(NamingStrategyType := GetType(LiteralKeyDictionaryNamingStrategy))> _
    Public Class LiteralKeyDictionary(Of TValue)
        Inherits Dictionary(Of String, TValue)
    End Class
    
    Public Class LiteralKeyDictionaryNamingStrategy
        Inherits DefaultNamingStrategy
    
        Public Sub New()
            ProcessDictionaryKeys = False
        End Sub
    End Class
    
  • ItemConverterTypeItemConverterParametersItemIsReferenceItemReferenceLoopHandlingItemTypeNameHandling允许自定义字典的序列化方式。

    例如,在以下字典类型中,值始终在启用reference preservation 的情况下存储:

    <JsonDictionary(ItemIsReference := true)> _
    Public Class ReferenceObjectDictionary(of TKey, TValue As {Class, New})
        Inherits Dictionary(Of TKey, TValue)
    End Class
    

    或者,对于包含 enum 值的字典类型,您可以将 StringEnumConverter 应用为 ItemConverterType 以强制将值序列化为字符串。

【讨论】:

    【解决方案2】:

    @dbc 的答案很棒,+1(而且这种方法比使用TypeConverter 路线要少得多,因为它是明确的)。这是一个 F# riff/rip-off/port:

    [<JsonDictionary(NamingStrategyType =
                        typedefof<VerbatimKeyDictionaryNamingStrategy>)>]
    type VerbatimKeyDictionary<'value>(values : IDictionary<string,'value>) =
        inherit Dictionary<string,'value>(values)
        override this.Equals other =
            let that = other :?> IDictionary<string,'value>
            that <> null
            && this.Count = that.Count
            && Seq.isEmpty (this |> Seq.except that)
        override __.GetHashCode () = 0
    and VerbatimKeyDictionaryNamingStrategy() =
        inherit Newtonsoft.Json.Serialization.DefaultNamingStrategy(
             ProcessDictionaryKeys = false)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-17
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      相关资源
      最近更新 更多