Json.NET反序列化或序列化json字符串,并将属性映射到运行时定义的不同属性名称 [英] Json.NET deserialize or serialize json string and map properties to different property names defined at runtime

查看:140
本文介绍了Json.NET反序列化或序列化json字符串,并将属性映射到运行时定义的不同属性名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下JSON字符串:

I have the following JSON string:

{
    "values": {
        "details": {
            "property1": "94",
            "property2": "47",
            "property3": "32",
            "property4": 1
        },
        count: 4
    }
}     

我将其映射到以下模型:

I am going to map this to the following model:

public class Details
{
    public string property1 { get; set; }
    public string property2 { get; set; }
    public string property3 { get; set; }
    public int property4 { get; set; }
}

public class Values
{
    public Details details { get; set; }
    public int count { get; set; }
}

public class RootObject
{
    public Values values { get; set; }
}

当我反序列化此JSON字符串时,我希望能够在运行时将这些属性名称映射到其他名称:

I want to be able to map the these property names to different names at runtime when deserializing this JSON string like this:

JsonConvert.DeserializeObject<RootObject>(jsonString);

例如,在反序列化过程中,我希望将"property1"的名称反序列化为"differen_property_name1"或"differen_property_name2"或"differen_property_name3". 因为我正在运行时选择新名称(将"property1"名称更改为的新名称),所以无法使用此处建议的通过JsonPropertyAttribute使用解决方案:

For example, in the deserialization process, I want the deserialize the name of "property1" to "differen_property_name1" or "differen_property_name2" or "differen_property_name3". Because I am choosing the new name at runtime (the new name to which I will change the "property1" name to), I can't use the solution using JsonPropertyAttribute, as suggested here:

.NET NewtonSoft JSON反序列化映射到其他财产名称

以上问题的答案之一(杰克的答案)使用DefaultContractResolver的继承,但在这种情况下似乎不起作用.

One of the answers of the above question (Jack's answer) uses inheritance of DefaultContractResolver but it doesn't seem to work in that case.

更新

稍后,我需要序列化从反序列化获得的对象,并将属性映射到在运行时定义的不同属性名称. 我使用了Brian建议的相同方法进行序列化:

Later on, I needed to serialize the object I got from the deserialization and map the properties to different property names, defined at runtime. I used the same method as Brian proposed to do the serialization:

我用字典来映射我的新属性名称:

I used the dictionary to map my new property names:

var map = new Dictionary<Type, Dictionary<string, string>>
{
    { 
        typeof(Details), 
        new Dictionary<string, string>
        {
            {"property1", "myNewPropertyName1"},
            {"property2", "myNewPropertyName2"},
            {"property3", "myNewPropertyName3"},
            {"property4", "myNewPropertyName4"}
        }
    }
};    

然后我使用Brian的DynamicMappingResolver序列化对象,如下所示:

and then I used Brian's DynamicMappingResolver to serialize the object like this:

var settings = new JsonSerializerSettings
{
    ContractResolver = new DynamicMappingResolver(map)
};

var root = JsonConvert.SerializeObject(myObjectInstance, settings);            

推荐答案

您可以使用自定义ContractResolver来执行此操作.基本上,这与将[JsonProperty]属性放在要映射到不同JSON属性名称的每个类成员上的想法相同,除了通过解析器以编程方式进行操作外.在反序列化之前进行设置时,可以将所需映射的字典传递给解析器.

You could use a custom ContractResolver to do this. Basically it is the same idea as putting a [JsonProperty] attribute on each class member for which you want to map to a different JSON property name, except you do it programmatically via the resolver. You can pass a dictionary of your desired mappings to the resolver when setting it up just before deserializing.

自定义解析器代码如下所示:

Here is what the custom resolver code might look like:

class DynamicMappingResolver : DefaultContractResolver
{
    private Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap;

    public DynamicMappingResolver(Dictionary<Type, Dictionary<string, string>> memberNameToJsonNameMap)
    {
        this.memberNameToJsonNameMap = memberNameToJsonNameMap;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        Dictionary<string, string> dict;
        string jsonName;
        if (memberNameToJsonNameMap.TryGetValue(member.DeclaringType, out dict) && 
            dict.TryGetValue(member.Name, out jsonName))
        {
            prop.PropertyName = jsonName;
        }
        return prop;
    }
}

要使用解析器,请首先构造一个包含您的映射的Dictionary<Type, Dictionary<string, string>>.外字典的键是您要映射其属性的类类型.内部字典是类属性名称到JSON属性名称的映射.您只需为其名称与JSON不匹配的属性提供映射.

To use the resolver, first construct a Dictionary<Type, Dictionary<string, string>> containing your mappings. The outer dictionary's key is the the class type(s) whose properties you want to map; the inner dictionary is a mapping of the class property names to JSON property names. You only need to provide a mapping for the properties whose names don't already match the JSON.

例如,如果您的JSON看起来像这样(请注意details对象内部属性的更改名称)...

So, for example, if your JSON looked like this (notice the changed names of the properties inside the details object)...

{
    "values": {
        "details": {
            "foo": "94",
            "bar": "47",
            "baz": "32",
            "quux": 1
        },
        count: 4
    }
}

...并且您想将其映射到问题中的类,则可以这样创建字典:

...and you wanted to map it to the classes in your question, you would create the dictionary like this:

var map = new Dictionary<Type, Dictionary<string, string>>
{
    { 
        typeof(Details), 
        new Dictionary<string, string>
        {
            {"property1", "foo"},
            {"property2", "bar"},
            {"property3", "baz"},
            {"property4", "quux"}
        }
    }
};

最后一步是使用新的解析器实例设置序列化程序设置,为它提供您刚刚构建的映射字典,然后将设置传递给JsonConvert.DeserializeObject().

The last step is to set up the serializer settings with a new resolver instance, giving it the mapping dictionary you just constructed, and then pass the settings to JsonConvert.DeserializeObject().

var settings = new JsonSerializerSettings
{
    ContractResolver = new DynamicMappingResolver(map)
};

var root = JsonConvert.DeserializeObject<RootObject>(json, settings);

这是一个演示: https://dotnetfiddle.net/ULkB0J

这篇关于Json.NET反序列化或序列化json字符串,并将属性映射到运行时定义的不同属性名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆