C# 使用JSON.net将非数组JSON对象解析为数组
我正在使用一个外部API,它根据计数将属性作为数组或对象返回。处理这个问题的好方法是什么 作为数组返回:C# 使用JSON.net将非数组JSON对象解析为数组,c#,arrays,json,json.net,deserialization,C#,Arrays,Json,Json.net,Deserialization,我正在使用一个外部API,它根据计数将属性作为数组或对象返回。处理这个问题的好方法是什么 作为数组返回: { "contacts": { "address": [ { "id": "47602070", "type": "Work", "street": "MyStreet", "city": "MyCity",
{
"contacts": {
"address": [
{
"id": "47602070",
"type": "Work",
"street": "MyStreet",
"city": "MyCity",
"zip": "12345",
"country": "USA"
},
{
"id": "47732816",
"type": "GPS",
"street": "50.0,30.0"
}
]
}
}
{
"contacts": {
"address": {
"id": "47602070",
"type": "Work",
"street": "MyStreet",
"city": "MyCity",
"zip": "12345",
"country": "USA"
}
}
}
作为对象返回:
{
"contacts": {
"address": [
{
"id": "47602070",
"type": "Work",
"street": "MyStreet",
"city": "MyCity",
"zip": "12345",
"country": "USA"
},
{
"id": "47732816",
"type": "GPS",
"street": "50.0,30.0"
}
]
}
}
{
"contacts": {
"address": {
"id": "47602070",
"type": "Work",
"street": "MyStreet",
"city": "MyCity",
"zip": "12345",
"country": "USA"
}
}
}
我认为一种解决方法是使用自定义反序列化程序,为对象大小写返回长度为1的数组,为数组大小写返回默认反序列化,但我还不知道怎么做
我尝试将对象反序列化为一个数组,希望Json.net能帮我处理这个问题,但没有成功 一个定制的JSON.NET转换器可能会在这里实现这一点。没那么难 对于DateTime属性,可以按如下方式执行。只需使用自定义转换器装饰有问题的属性
[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
[JsonProperty(PropertyName = "creation_date")]
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime CreationDate { get; set; }
}
public class UnixDateTimeConverter : DateTimeConverterBase
{
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{ ...}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{ ... }
}
JSON.NET提供了大部分管道。只需从基极转换器派生
[JsonObject(MemberSerialization.OptIn)]
public class MyClass
{
[JsonProperty(PropertyName = "creation_date")]
[JsonConverter(typeof(UnixDateTimeConverter))]
public DateTime CreationDate { get; set; }
}
public class UnixDateTimeConverter : DateTimeConverterBase
{
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{ ...}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{ ... }
}
您所要做的就是实现ReadJson(反序列化)和WriteJson(序列化)方法
您可以在此处找到完整的示例:
对于你的特殊问题,你需要更多的控制。请尝试以下类型的转换器:
public class Contact
{
private List<Address> _addresses = new List<Address>();
public IEnumerable<Address> Addresses { get { return _addresses; }
}
public class ContactConverter : CustomCreationConverter<Contact>
{
public override Contact Create(Type objectType)
{
return new Contact();
}
public override object ReadJson(JsonReader reader, Type objectType, object
existingValue, JsonSerializer serializer)
{
var mappedObj = new Contact();
// Parse JSON data here
// ...
return mappedObj;
}
}
公共类联系人
{
私人名单
在这种情况下,在取消搜索时需要传递自定义转换器
Contact contact =
JsonConvert.DeserializeObject<Contact>(json, new ContactConverter());
联系人=
反序列化对象(json,new ContactConverter());
基于克里斯托夫·吉尔斯的观点,以下是我最终的做法
创建自定义JSON转换器,以便始终将JSON解析为数组。如果JSON是非数组对象,则反序列化该对象并将其包装到数组中
使用自定义转换器属性标记相应的属性
自定义转换器
public class JsonToArrayConverter<T> : CustomCreationConverter<T[]>
{
public override T[] Create(Type objectType)
{
// Default value is an empty array.
return new T[0];
}
public override object ReadJson(JsonReader reader, Type objectType, object
existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
// JSON object was an array, so just deserialize it as usual.
object result = serializer.Deserialize(reader, objectType);
return result;
}
else
{
// JSON object was not an arry, so deserialize the object
// and wrap it in an array.
var resultObject = serializer.Deserialize<T>(reader);
return new T[] {resultObject};
}
}
}
公共类JsonToArrayConverter:CustomCreationConverter
{
公共重写T[]创建(类型objectType)
{
//默认值为空数组。
返回新的T[0];
}
公共重写对象ReadJson(JsonReader,类型objectType,对象
现有值,JsonSerializer序列化程序)
{
if(reader.TokenType==JsonToken.StartArray)
{
//JSON对象是一个数组,所以像往常一样反序列化它。
对象结果=序列化程序。反序列化(读取器,对象类型);
返回结果;
}
其他的
{
//JSON对象不是arry,因此反序列化该对象
//并将其包装成一个数组。
var resultObject=serializer.Deserialize(读取器);
返回新的T[]{resultObject};
}
}
}
问题示例的数据结构
public class Organisation
{
public Contacts contacts;
}
public class Address
{
public string id;
public string street;
public string city;
public string type;
public string zip;
public string country;
}
public class Contacts
{
// Tell JSON.net to use the custom converter for this property.
[JsonConverter(typeof(JsonToArrayConverter<Address>))]
public Address[] address;
}
公共类组织
{
公众接触;
}
公共课堂演讲
{
公共字符串id;
公众街;;
公共字符串城市;
公共字符串类型;
公共字符串压缩;
公共字符串国家;
}
公共类联系人
{
//告诉JSON.net为此属性使用自定义转换器。
[JsonConverter(类型(JsonToArrayConverter))]
公共广播[]地址;
}
注意:您可以使用普通的转换器,而不是使用CustomCreationConverter
。例如,我使用的是这样的转换器:
public class SingleToArrayConverter<T> : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var items = (IEnumerable<T>)value;
if (value == null || !items.Any())
{
writer.WriteNull();
}
else if (items.Count() == 1)
{
serializer.Serialize(writer, items.ElementAt(0));
}
else
{
serializer.Serialize(writer, items);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (!CanConvert(objectType))
{
throw new NotSupportedException();
}
if (reader.TokenType == JsonToken.Null)
{
reader.Skip();
return null;
}
else if (reader.TokenType == JsonToken.StartObject)
{
return new T[] { serializer.Deserialize<T>(reader) };
}
else
{
return serializer.Deserialize<T[]>(reader);
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(IEnumerable<T>);
}
}
公共类SingleToArrayConverter:JsonConverter
{
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
变量项=(IEnumerable)值;
if(value==null | |!items.Any())
{
WriteNull();
}
else if(items.Count()==1)
{
serializer.Serialize(writer,items.ElementAt(0));
}
其他的
{
序列化器。序列化(编写器、项);
}
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
如果(!CanConvert(对象类型))
{
抛出新的NotSupportedException();
}
if(reader.TokenType==JsonToken.Null)
{
reader.Skip();
返回null;
}
else if(reader.TokenType==JsonToken.StartObject)
{
返回新的T[]{serializer.Deserialize(reader)};
}
其他的
{
返回序列化程序。反序列化(读取器);
}
}
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(IEnumerable);
}
}
感谢您的全面投入。从您的示例中,我得到了成功,并发布了最终结果。