首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于.Net (C#)中字段的json反序列化

基于.Net (C#)中字段的json反序列化
EN

Stack Overflow用户
提问于 2014-05-09 14:20:47
回答 5查看 4K关注 0票数 8

我正在编写一个应用程序,它获取一个Json对象列表,如下所示:

代码语言:javascript
复制
[
   {
       "ObjectType": "apple",
       "ObjectSize": 35,
       "ObjectCost": 4,
       "ObjectTaste": "good",
       "ObjectColor": "golden"
   },
   {
       "ObjectType": "books",
       "ObjectSize": 53,
       "ObjectCost": 7,
       "Pages": 100
   },
   {
       "ObjectType": "melon",
       "ObjectSize": 35,
       "ObjectTaste": "good",
       "ObjectCost": 5
   },
   {
       "ObjectType": "apple",
       "ObjectSize": 29,
       "ObjectCost": 8,
       "ObjectTaste": "almost good",
       "ObjectColor": "red"
   }
  ]

我想要做一个基类ItemToSell (大小,成本),并从它派生苹果,甜瓜和图书,然后使反序列化基于"ObjectType“字段的任何类适合。我希望它构建一个ItemToSell对象列表,每个对象都是苹果、瓜或书籍。

我怎么能在.Net上做到这一点?

(预先谢谢:)

编辑:我知道如何在一个Big中反序列化它,它可以包含的所有字段,比如:Base(ObjectType,ObjectSize,ObjectCost,ObjectColor,Pages)。但是我希望它通过ObjectType来区分类,这样我就不会有任何有用的字段,比如每个图书条目的页面字段,或者每本书的ObjectTaste字段。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-05-09 14:41:19

不久前我也遇到了同样的问题。

您可以使用Json.NET,但如果您无法控制json文档(如:“它已被其他框架序列化”),则需要创建如下所示的自定义JsonConverter:

代码语言:javascript
复制
class MyItemConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ItemToSell).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        string discriminator = (string)obj["ObjectType"];

        ItemToSell item;
        switch (discriminator)
        {
            case "apple":
                item = new Apple();
                break;
            case "books":
                item = new Books();
                break;
            case "melon":
                item = new Melon();
                break;
            default:
                throw new NotImplementedException();
        }

        serializer.Populate(obj.CreateReader(), item);

        return item;

    }


    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {

    }
}

然后需要将它添加到JsonSerializerSettings的转换器中,如下所示:

代码语言:javascript
复制
JsonSerializerSettings settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,

};
settings.Converters.Add(new MyItemConverter());
var items = JsonConvert.DeserializeObject<List<ItemToSell>>(response, settings);
票数 15
EN

Stack Overflow用户

发布于 2014-05-09 14:45:35

您可以使用CustomCreationConverter。这使您可以连接到反序列化过程。

代码语言:javascript
复制
public abstract class Base
{
    public string Type { get; set; }
}

class Foo : Base
{
    public string FooProperty { get; set; }
}

class Bar : Base
{
    public string BarProperty { get; set; }
}

class CustomSerializableConverter : CustomCreationConverter<Base>
{
    public override Base Create(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);

        var type = (string)jObject.Property("Type");
        Base target;
        switch (type)
        {
            case "Foo":
                target = new Foo();
                break;
            case "Bar":
                target = new Bar();
                break;
            default:
                throw new InvalidOperationException();
        }
        serializer.Populate(jObject.CreateReader(), target);
        return target;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var json = "[{Type:\"Foo\",FooProperty:\"A\"},{Type:\"Bar\",BarProperty:\"B\"}]";
        List<Base> bases = JsonConvert.DeserializeObject<List<Base>>(json, new CustomSerializableConverter());
    }
}
票数 4
EN

Stack Overflow用户

发布于 2014-05-09 14:43:45

这不是一个答案,但在C# 6.0中,您可以这样做:

代码语言:javascript
复制
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using Newtonsoft.Json.Linq;
  [TestMethod]
  public void JsonWithDollarOperatorStringIndexers()
  {

      // Additional data types eliminated for elucidation
      string jsonText = @"
        {
          'Byte':  {
            'Keyword':  'byte',
            'DotNetClassName':  'Byte',
            'Description':  'Unsigned integer',
            'Width':  '8',
            'Range':  '0 to 255'
                    },
          'Boolean':  {
            'Keyword':  'bool',
            'DotNetClassName':  'Boolean',
            'Description':  'Logical Boolean type',
            'Width':  '8',
            'Range':  'True or false.'
                      },
        }";
      JObject jObject = JObject.Parse(jsonText);
      Assert.AreEqual("bool", jObject.$Boolean.$Keyword);
    }

取自这里。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23566980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档