使用Json.net将非数组JSON对象解析为数组

ang*_*sen 6 c# arrays json json.net deserialization

我正在使用外部API,它根据计数返回属性作为数组或对象.处理这个问题的好方法是什么?

作为数组返回:

{
    "contacts": {
        "address": [
            {
                "id": "47602070",
                "type": "Work",
                "street": "MyStreet",
                "city": "MyCity",
                "zip": "12345",
                "country": "USA"
            },
            {
                "id": "47732816",
                "type": "GPS",
                "street": "50.0,30.0"
            }
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

作为对象返回:

{
    "contacts": {
        "address": {
            "id": "47602070",
            "type": "Work",
            "street": "MyStreet",
            "city": "MyCity",
            "zip": "12345",
            "country": "USA"
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在想一个解决方法是使用自定义反序列化器并返回一个长度为1的数组用于对象大小写,并为数组大小写默认反序列化,但我不知道该怎么做.

我尝试将对象反序列化为一个数组,并希望Json.net能为我处理这个案例,但没有骰子.

ang*_*sen 5

根据Christophe Geers的回答,这就是我最终要做的事情.

  1. 创建自定义JSON转换器以始终将JSON解析为数组.如果JSON是非数组对象,则反序列化该对象并将其包装在数组中.

  2. 使用自定义转换器属性标记相应的属性.

定制转换器

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};
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题示例的数据结构

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;
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ers 3

自定义 JSON.NET 转换器可能会解决这个问题。这并不难。

\n\n

对于 DateTime 属性,您可以按如下方式进行操作。只需使用自定义转换器装饰相关属性即可。

\n\n
[JsonObject(MemberSerialization.OptIn)]\npublic class MyClass\n{\n    [JsonProperty(PropertyName = "creation_date")]\n    [JsonConverter(typeof(UnixDateTimeConverter))]\n    public DateTime CreationDate { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

JSON.NET 提供了大部分管道。只需从基本转换器派生即可。

\n\n
public class UnixDateTimeConverter : DateTimeConverterBase\n{\n    public override void WriteJson(JsonWriter writer, object value, \n                                   JsonSerializer serializer)\n    { ...}\n\n    public override void WriteJson(JsonWriter writer, object value, \n                                   JsonSerializer serializer)\n    { ... } \n}  \n
Run Code Online (Sandbox Code Playgroud)\n\n

您所要做的就是实现 ReadJson(反序列化)和 WriteJson(序列化)方法。

\n\n

您可以在这里找到完整的示例:

\n\n

编写自定义 Json.NET DateTime 转换器

\n\n

对于您的特定问题,您需要更多的控制。尝试以下类型的转换器:

\n\n
public class Contact\n{ \n   private List<Address> _addresses = new List<Address>();       \n   public IEnumerable<Address> Addresses { get { return _addresses; }\n}\n\npublic class ContactConverter : CustomCreationConverter<Contact>\n{\n    public override Contact Create(Type objectType)\n    {\n        return new Contact();\n    }\n\n    public override object ReadJson(JsonReader reader, Type objectType, object \n        existingValue, JsonSerializer serializer)\n    {\n        var mappedObj = new Contact();\n\n        // Parse JSON data here\n        // ...\n\n        return mappedObj;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用像上面这样的自定义转换器,您可以自己解析 JSON 数据并根据需要编写联系人对象。

\n\n

我修改了在这里找到的示例:

\n\n

JSON.NET 自定义转换器\xe2\x80\x93A 快速浏览

\n\n

在这种情况下,您需要在反串化时传递自定义转换器。

\n\n
Contact contact = \n    JsonConvert.DeserializeObject<Contact>(json, new ContactConverter());\n
Run Code Online (Sandbox Code Playgroud)\n