我有以下JSON字符串:
{ "values": { "details": { "property1": "94", "property2": "47", "property3": "32", "property4": 1 }, count: 4 } }
我将其映射到以下模型:
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字符串时在运行时将这些属性名称映射到其他名称:
JsonConvert.DeserializeObject<RootObject>(jsonString);
例如,在反序列化过程中,我想将“ 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"} } } };
然后我使用Brian的DynamicMappingResolver序列化对象,如下所示:
var settings = new JsonSerializerSettings { ContractResolver = new DynamicMappingResolver(map) }; var root = JsonConvert.SerializeObject(myObjectInstance, settings);
您可以使用自定义ContractResolver来执行此操作。基本上,这与[JsonProperty]在每个要映射到其的类成员上将属性映射到不同JSON属性名称的想法相同,只是通过解析器以编程方式进行操作。在反序列化之前进行设置时,可以将所需映射的字典传递给解析器。
ContractResolver
[JsonProperty]
自定义解析器代码如下所示:
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不匹配的属性提供映射。
Dictionary<Type, Dictionary<string, string>>
因此,例如,如果您的JSON如下所示(请注意details对象内部属性的更改名称)…
details
{ "values": { "details": { "foo": "94", "bar": "47", "baz": "32", "quux": 1 }, count: 4 } }
…并且您想将其映射到问题中的类,则可以这样创建字典:
var map = new Dictionary<Type, Dictionary<string, string>> { { typeof(Details), new Dictionary<string, string> { {"property1", "foo"}, {"property2", "bar"}, {"property3", "baz"}, {"property4", "quux"} } } };
最后一步是使用新的解析器实例设置序列化程序设置,为其提供刚刚构造的映射字典,然后将设置传递给JsonConvert.DeserializeObject()。
JsonConvert.DeserializeObject()
var settings = new JsonSerializerSettings { ContractResolver = new DynamicMappingResolver(map) }; var root = JsonConvert.DeserializeObject<RootObject>(json, settings);
这是一个演示:https : //dotnetfiddle.net/ULkB0J