【问题标题】:Deserialization does not work for dynamic properties if using Json.NET attributes如果使用 Json.NET 属性,则反序列化不适用于动态属性
【发布时间】:2014-05-21 01:52:46
【问题描述】:

问题

大家好,

我正在尝试反序列化具有已知(静态)和未知(动态)属性的 Json 字符串。为此,我使用 Json.NET 和 System.Dynamic.DynamicObject。 在我的第一次尝试中,我使用 Json.NET 特定的 Serialization Attributes 来配置(反)序列化程序。但是,在这种情况下,Json 字符串中的动态属性不会被反序列化。但是当我切换到本机 .NET 属性([DataContract][DataMember])时,动态属性会被反序列化,我可以在创建的动态对象中访问它们。

这种行为是有意的吗?我是否缺少任何具有 Json.NET 属性的配置来获得相同的反序列化行为?

任何澄清将不胜感激!

细节

这里我提供了我的实现细节(使用 Json.NET 属性)。我正在使用 .NET 4.5 和 Json.NET 6.0.2

因为我有多种消息类型,具有静态和动态属性,所以我引入了一个基类,它实现了动态处理属性:

[JsonObject]
internal abstract class DynamicMessage : DynamicObject
{
    [JsonProperty]
    public Dictionary<string, object> dynamicProperties = new Dictionary<string, object();

    public override bool TryGetMember(GetMemberBinder binder, out object result) {...}
    public override bool TrySetMember(SetMemberBinder binder, object value) {...}
}

具体的子类如下所示:

[JsonObject]
internal class ItemMessage : DynamicMessage
{
    [JsonPropertyAttribute(PropertyName = "id")]
    internal long Id;
    [JsonPropertyAttribute(PropertyName = "parent_item");
    internal long ParentItemId;
    ...
}

我尝试像这样反序列化以下字符串:

jsonString = @{'id':1,
'parent_item':5,
'my_dynamic_property_1' : 1337,
'my_dynamic_property_2' : 'my_dynamic_property_2'}

JsonSerializer serializer  = new JsonSerializer();
dynamic itemMessage = serializer.Deserialize<ItemMessage>(new JsonTextReader(jsonString));

正如我在开始时指出的那样,如果我使用属性[JsonObject][JsonProperty],所有静态属性都会正确反序列化并绑定到 POCO 属性,但我缺少动态属性@ 987654330@和my_dynamic_property_2

当我更改为[DataContract][JsonObject])和[DataMember][JsonProperty])时,Json 中的动态属性也将被反序列化,我可以调用

itemMessage.my_dynamic_property_1; //=1337
itemMessage.my_dynamic_property_2; //="my_dynamic_property_2"

【问题讨论】:

    标签: c# wcf json.net


    【解决方案1】:

    [JsonProperty] 始终将 JSON 中的单个属性绑定到类中的单个成员。您不能使用它将多个 JSON 属性绑定到单个字典。那样不行。

    但是,Json.Net 确实有一个 [JsonExtensionData] 属性,可以按照您想要的方式工作。试试这个:

    [JsonObject]
    internal abstract class DynamicMessage : DynamicObject
    {
        [JsonExtensionData]
        public Dictionary<string, object> dynamicProperties = 
                                                 new Dictionary<string, object>();
        ...
    }
    

    【讨论】:

    • 谢谢布赖恩!你让我今天一整天都感觉很好!这正是我正在寻找的答案。
    【解决方案2】:

    这可能不是您要查找的内容,但您始终可以反序列化为字典。

    var jsonString = @"{'id':1,
    'parent_item':5,
    'parent_details':{'name': 'parent_name', 'description': 'parent description'},
    'array':[1,2,3,4,5,6,7],
    'my_dynamic_property_1' : 1337,
    'my_dynamic_property_2' : 'my_dynamic_property_2'}";
    
    Dictionary<string, dynamic> values = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
    

    我添加了一个嵌套对象,因此您可以看到它仍然反序列化为另一个具有动态值的字典以保持所有内容的正确键入,我还添加了一个整数数组用于相同目的。

    您可以像这样访问您的动态属性:

    values[my_dynamic_property_1];
    

    虽然我建议像这样转换已知类型:

    var prop1 = (int)values["my_dynamic_property_1"];
    

    对于嵌套对象,你可以像这样直接访问成员:

    var parentDescription = values["parent_details"]["name"];
    

    【讨论】:

    • 嗨 Smeegs,非常感谢您!但这确实不是我正在寻找的答案。我希望得到任何澄清,为什么动态 Json 属性的反序列化仅在我使用本机 .NET 序列化属性时才有效。
    猜你喜欢
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 2020-06-08
    • 2021-05-26
    • 2011-01-16
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多