一尘不染

使用JSON.NET反序列化JSON,其中值是字段名称

json

我有一个非常不理想的情况,要求我反序列化JSON,其中值是JSON.NET的字段名称。假设我具有以下结构正确的JSON:

{
    "name": "tugberk",
    "roles": [
        { "id": "1", "name": "admin" },
        { "id": "2", "name": "guest" }
    ]
}

使用JSON.NET将其反序列化为CLR对象非常容易:

class Program
{
    static void Main(string[] args)
    {
        var camelCaseSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };

        var text = File.ReadAllText("user_normal.txt");
        var obj = JsonConvert.DeserializeObject<User>(text, camelCaseSettings);
    }
}

public class User
{
    public string Name { get; set; }
    public Role[] Roles { get; set; }
}

public class Role
{
    public int Id { get; set; }
    public string Name { get; set; }
}

但是,在当前情况下,我有以下可怕的JSON,就值而言,它等效于上述JSON:

{
    "name": "tugberk",
    "roles": {
        "1": { "name": "admin" },
        "2": { "name": "guest" }
    }
}

如您所见,rolesfield不是数组。这是一个包含其他值作为对象的对象,其唯一键作为其字段名称(这太可怕了)。User使用JSON.NET
将JSON反序列化为上述类的最佳方法是什么?


阅读 230

收藏
2020-07-27

共1个答案

一尘不染

您可以创建一个JsonConverter序列化/反序列化的自定义Role[]。然后,您可以像这样装饰您的Roles媒体资源JsonConverterAttribute

public class User
{
    public string Name { get; set; }
    [JsonConverter(typeof(RolesConverter))]
    public Role[] Roles { get; set; }
}

在转换器类中,您可以读取一个对象并返回一个数组。您的转换器类可能如下所示:

class RolesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Role[]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // deserialize as object
        var roles = serializer.Deserialize<JObject>(reader);
        var result = new List<Role>();

        // create an array out of the properties
        foreach (JProperty property in roles.Properties())
        {
            var role = property.Value.ToObject<Role>();
            role.Id = int.Parse(property.Name);
            result.Add(role);
        }

        return result.ToArray();
    }


    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
2020-07-27