如何使用Newtonsoft JSON.NET将JSON反序列化为IEnumerable <BaseType>

And*_*ock 66 c# json.net

鉴于此JSON:

[
  {
    "$id": "1",
    "$type": "MyAssembly.ClassA, MyAssembly",
    "Email": "me@here.com",
  },
  {
    "$id": "2",
    "$type": "MyAssembly.ClassB, MyAssembly",
    "Email": "me@here.com",
  }
]
Run Code Online (Sandbox Code Playgroud)

和这些类:

public abstract class BaseClass
{
    public string Email;
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
Run Code Online (Sandbox Code Playgroud)

如何将JSON反序列化为:

IEnumerable<BaseClass> deserialized;
Run Code Online (Sandbox Code Playgroud)

我不能使用,JsonConvert.Deserialize<IEnumerable<BaseClass>>()因为它抱怨BaseClass是抽象的.

And*_*ock 85

你需要:

 JsonSerializerSettings settings = new JsonSerializerSettings
                 {
                     TypeNameHandling = TypeNameHandling.All
                 };

string strJson = JsonConvert.SerializeObject(instance, settings);
Run Code Online (Sandbox Code Playgroud)

所以JSON看起来像这样:

{
  "$type": "System.Collections.Generic.List`1[[MyAssembly.BaseClass, MyAssembly]], mscorlib",
  "$values": [
    {
      "$id": "1",
      "$type": "MyAssembly.ClassA, MyAssembly",
      "Email": "me@here.com",
    },
    {
      "$id": "2",
      "$type": "MyAssembly.ClassB, MyAssembly",
      "Email": "me@here.com",
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

然后你可以反序列化它:

BaseClass obj = JsonConvert.DeserializeObject<BaseClass>(strJson, settings)
Run Code Online (Sandbox Code Playgroud)

文档:TypeNameHandling设置

  • 请注意,这会使您的端点面临安全问题:https://www.alphabot.com/security/blog/2017/net/How-to-configure-Json.NET-to-create-a-vulnerable-web- API.html (2认同)
  • 好的解决方案,但是在应用之前请先阅读https://www.alphabot.com/security/blog/2017/net/How-to-configure-Json.NET-to-create-a-vulnerable-web-API.html (2认同)

chr*_*389 17

这是一种方法,无需在json中填充$ type.

一个Json转换器:

public class FooConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BaseFoo));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        if (jo["FooBarBuzz"].Value<string>() == "A")
            return jo.ToObject<AFoo>(serializer);

        if (jo["FooBarBuzz"].Value<string>() == "B")
            return jo.ToObject<BFoo>(serializer);

        return null;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它:

var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result, new JsonSerializerSettings() 
{ 
    Converters = { new FooConverter() }
});
Run Code Online (Sandbox Code Playgroud)

取自这里

  • 这个答案非常好,但如果缺少 'FooBarBuzz' 会出错(即您需要格式一致的 json)。您还可以检查该字段是否存在,如下所示 - /sf/answers/1341115541/ (2认同)

小智 6

反序列化时使用以下JsonSerializerSettings构造:

new JsonSerializerSettings()
{
    TypeNameHandling = TypeNameHandling.Objects
})
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

58728 次

最近记录:

6 年,1 月 前