Avi*_* K. 9 c# json json.net json-deserialization
我有以下JSON字符串:
{
"values": {
"details": {
"property1": "94",
"property2": "47",
"property3": "32",
"property4": 1
},
count: 4
}
}
Run Code Online (Sandbox Code Playgroud)
我将把它映射到以下模型:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在运行时将这些属性名称映射到不同的名称,这样反序列化此JSON字符串,如下所示:
JsonConvert.DeserializeObject<RootObject>(jsonString);
Run Code Online (Sandbox Code Playgroud)
例如,在反序列化过程中,我希望将"property1"的名称反序列化为"differen_property_name1"或"differen_property_name2"或"differen_property_name3".因为我在运行时选择新名称(我要将"property1"名称更改为的新名称),我不能使用JsonPropertyAttribute的解决方案,如下所示:
.NET NewtonSoft JSON将映射反序列化为不同的属性名称
上述问题的答案之一(杰克的回答)使用了DefaultContractResolver的继承,但在这种情况下它似乎不起作用.
更新
稍后,我需要序列化从反序列化中获得的对象,并将属性映射到在运行时定义的不同属性名称.我使用了与Brian建议进行序列化相同的方法:
我用字典来映射我的新属性名称:
var map = new Dictionary<Type, Dictionary<string, string>>
{
{
typeof(Details),
new Dictionary<string, string>
{
{"property1", "myNewPropertyName1"},
{"property2", "myNewPropertyName2"},
{"property3", "myNewPropertyName3"},
{"property4", "myNewPropertyName4"}
}
}
};
Run Code Online (Sandbox Code Playgroud)
然后我使用Brian的DynamicMappingResolver来序列化对象,如下所示:
var settings = new JsonSerializerSettings
{
ContractResolver = new DynamicMappingResolver(map)
};
var root = JsonConvert.SerializeObject(myObjectInstance, settings);
Run Code Online (Sandbox Code Playgroud)
您可以使用自定义ContractResolver来执行此操作.基本上它与将一个[JsonProperty]属性放在要映射到不同JSON属性名称的每个类成员上的想法相同,除非您通过解析程序以编程方式执行此操作.在反序列化之前进行设置时,可以将所需映射的字典传递给解析器.
以下是自定义解析程序代码的外观:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
要使用解析器,首先构造一个Dictionary<Type, Dictionary<string, string>>包含映射的解析器.外部字典的键是要映射其属性的类类型; 内部字典是类属性名称到JSON属性名称的映射.您只需要为名称与JSON不匹配的属性提供映射.
因此,例如,如果您的JSON看起来像这样(注意details对象内部属性的更改名称)...
{
"values": {
"details": {
"foo": "94",
"bar": "47",
"baz": "32",
"quux": 1
},
count: 4
}
}
Run Code Online (Sandbox Code Playgroud)
...并且您想将它映射到问题中的类,您可以像这样创建字典:
var map = new Dictionary<Type, Dictionary<string, string>>
{
{
typeof(Details),
new Dictionary<string, string>
{
{"property1", "foo"},
{"property2", "bar"},
{"property3", "baz"},
{"property4", "quux"}
}
}
};
Run Code Online (Sandbox Code Playgroud)
最后一步是使用新的解析器实例设置序列化程序设置,为其提供刚构建的映射字典,然后将设置传递给JsonConvert.DeserializeObject().
var settings = new JsonSerializerSettings
{
ContractResolver = new DynamicMappingResolver(map)
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);
Run Code Online (Sandbox Code Playgroud)
这是一个演示:https://dotnetfiddle.net/ULkB0J
| 归档时间: |
|
| 查看次数: |
4700 次 |
| 最近记录: |