Newtonsoft JSON.NET解析为自定义键/值对对象的数组 [英] Newtonsoft JSON.NET parse to array of custom key/value pair objects
问题描述
我在解析给定的JSON数据时遇到了一个奇怪的问题.我有这个JSON结构:
I have this strange issue with parsing given JSON data. I have this JSON structure:
{"value":[
{"street":"Karlova 25"},
{"city":"Prague"},
{"gpsLat":"50.1571"},
{"gpsLon":"15.0482"}
]}
如何使用Newtonsoft JSON.NET库解析此结构?我尝试使用自己的JsonConverter类:
How to parse this structure using Newtonsoft JSON.NET library? I tried to use my own JsonConverter class:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer){
JArray jarray = (JArray)((JTokenReader)reader).CurrentToken;
List<AddressValue> values = new List<AddressValue>();
foreach (var jobj in jarray.Children<JObject>()){
foreach (JProperty prop in jobj.Properties()){
values.Add(new AddressValue() { Label = prop.Name, Value = prop.Value.ToString() });
}
}
return values.ToArray();
}
class AddressValue{
public string Label { get; set; }
public string Value { get; set; }
}
但是我有一个例外:
Exception thrown: 'Newtonsoft.Json.JsonSerializationException' in Newtonsoft.Json.DLL
Additional information: Unexpected token when deserializing object: StartObject. Path 'value[0]'.
我也试图将其保存到Dictionary:
I also tried to save this to Dictionary:
[JsonProperty(PropertyName = "value")]
public Dictionary<string, string> Value{get; set;}
但是我还有另一个例外:
But I have another exception:
$exception {"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {\"name\":\"value\"}) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON object (e.g. {\"name\":\"value\"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.\r\nPath 'param.value'."}
我做错了什么?谢谢您的回答.
What I am doing wrong? Thank you for your answers.
推荐答案
您似乎想要在JSON中将Dictionary<string, string>
表示为对象数组,其中每个嵌套对象都有一个来自字典的键和值.您可以使用以下转换器进行此操作:
It appears that you want to represent a Dictionary<string, string>
in your JSON as an array of objects, where each nested object has one key and value from the dictionary. You can do it with the following converter:
public class DictionaryToDictionaryListConverter<TKey, TValue> : JsonConverter
{
class DictionaryDTO : Dictionary<TKey, TValue>
{
public DictionaryDTO(KeyValuePair<TKey, TValue> pair) : base(1) { Add(pair.Key, pair.Value); }
}
public override bool CanConvert(Type objectType)
{
return typeof(IDictionary<TKey, TValue>).IsAssignableFrom(objectType) && objectType != typeof(DictionaryDTO);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var token = JToken.Load(reader);
var dict = (IDictionary<TKey, TValue>)(existingValue as IDictionary<TKey, TValue> ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
if (token.Type == JTokenType.Array)
{
foreach (var item in token)
using (var subReader = item.CreateReader())
serializer.Populate(subReader, dict);
}
else if (token.Type == JTokenType.Object)
{
using (var subReader = token.CreateReader())
serializer.Populate(subReader, dict);
}
return dict;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dict = (IDictionary<TKey, TValue>)value;
// Prevent infinite recursion of converters by using DictionaryDTO
serializer.Serialize(writer, dict.Select(p => new DictionaryDTO(p)));
}
}
然后按如下所示在您的容器类中使用它:
Then use it in your container class as follows:
public class RootObject
{
[JsonProperty("value")]
[JsonConverter(typeof(DictionaryToDictionaryListConverter<string, string>))]
public Dictionary<string, string> Value { get; set; }
}
请注意,如果键不是唯一的,转换器将在读取过程中引发异常.
Note that the converter will throw an exception during reading if the keys are not unique.
更新
对于AddressValue
,您可以使用以下转换器:
For AddressValue
you could use the following converter:
public class AddressValueConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(AddressValue);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var addressValue = (existingValue as AddressValue ?? new AddressValue());
var token = JObject.Load(reader);
var property = token.Properties().SingleOrDefault();
if (property != null)
{
addressValue.Label = property.Name;
addressValue.Value = (string)property.Value;
}
return addressValue;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var addressValue = (AddressValue)value;
serializer.Serialize(writer, new Dictionary<string, string> { { addressValue.Label, addressValue.Value } });
}
}
然后按如下所示使用它:
Then use it as follows:
[JsonConverter(typeof(AddressValueConverter))]
public class AddressValue
{
public string Label { get; set; }
public string Value { get; set; }
}
public class RootObject
{
[JsonProperty("value")]
public List<AddressValue> Value { get; set; }
}
在两个选项中都进行小提琴演奏此处.
Demo fiddle with both options here.
这篇关于Newtonsoft JSON.NET解析为自定义键/值对对象的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!