假设我有一些有3个对象和值的json
{
"SomeProperty": "42",
"Foo": "bar",
"Name001": "ABC_1",
"Type001": "D",
"Confidence001": "100",
...
"Name00N": "ABC_N",
"Type00N": "D",
"Confidence00N": "50",
}
我如何使用转换器/映射器将这3个对象分组到一个POCO中?
public class DeserializedJsonClass
{
public long SomeProperty {get;set;}
public string Foo {get;set;}
public EvaluationStat[] Evaluations {get;set;}
}
public class EvaluationStat
{
public string Name {get;set;}
public char Type {get;set;}
public int Confidence {get;set;}
}
我已经了解了牛顿软件的映射,我使用转换器将Y / N转换为bool
,将某些xml转换为XDocument
,但我无法弄清楚如何映射将这三个对象合二为一。
答案 0 :(得分:2)
解决问题的一种方法:
public class DeserializedJsonClass
{
public long SomeProperty { get; set; }
public string Foo { get; set; }
public IEnumerable<EvaluationStat> Evaluations { get; set; }
}
public class EvaluationStat
{
public string Name { get; set; }
public char Type { get; set; }
public int Confidence { get; set; }
}
// ...
private static DeserializedJsonClass Deserialize(string json)
{
// using Newtonsoft.Json
dynamic deserialized = JsonConvert.DeserializeObject(json);
DeserializedJsonClass result = new DeserializedJsonClass();
result.SomeProperty = deserialized.SomeProperty;
result.Foo = deserialized.Foo;
result.Evaluations = FetchEvaluations(deserialized);
return result;
}
private static IEnumerable<EvaluationStat> FetchEvaluations(dynamic json)
{
ICollection<string> names = new List<string>();
ICollection<char> types = new List<char>();
ICollection<int> confidences = new List<int>();
foreach (var prop in json)
{
if (prop.Name.StartsWith("Name"))
names.Add((string)prop.Value.Value);
else if (prop.Name.StartsWith("Type"))
types.Add(Convert.ToChar((string)prop.Value.Value));
else if (prop.Name.StartsWith("Confidence"))
confidences.Add(Convert.ToInt32((string)prop.Value.Value));
}
return names.Zip(types, (n, t) => new { Name = n, Type = t })
.Zip(confidences, (l, c) => new { Name = l.Name, Type = l.Type, Confidence = c })
.Select(t => new EvaluationStat()
{
Name = t.Name,
Type = t.Type,
Confidence = t.Confidence
});
}
答案 1 :(得分:1)
如果您能够更改源数据,则可以将此JSON反序列化为您提议的类。
[
{
"Name": "ABC_1",
"Type": "D",
"Confidence": "100"
},
...
{
"Name": "ABC_N",
"Type": "D",
"Confidence": "50"
}
]
答案 2 :(得分:1)
自定义JsonConvert是另一种方法
public class EvaluationStatJsonConverter : JsonConverter
{
public override bool CanConvert( Type objectType ) { return objectType == typeof( DeserializedJsonClass ); }
public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer )
{
var jsonObject = JObject.Load( reader );
var properties = typeof( EvaluationStat ).GetProperties();
var deserializedJsonClass = new DeserializedJsonClass
{
Evaluations = new EvaluationStat[jsonObject.Count / properties.Length]
};
for( var i = 1; i <= jsonObject.Count / properties.Length; i++ )
{
deserializedJsonClass.Evaluations[ i - 1 ] = new EvaluationStat();
foreach( var field in properties )
{
field.SetValue( deserializedJsonClass.Evaluations[ i - 1 ],
jsonObject[ $"{field.Name}{i:000}" ].ToObject( field.PropertyType ) );
}
}
return deserializedJsonClass;
}
public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer )
{
throw new NotImplementedException();
}
}
然后你想要使用它,你可以做到这一点
var jss = new JsonSerializerSettings();
jss.Converters.Add( new EvaluationStatJsonConverter() );
var result =
JsonConvert.DeserializeObject< DeserializedJsonClass >(
"your json content" ),
jss );
我同意其他评论,这是一个非常好的解决方案。