繁体   English   中英

根据.Net(C#)中的字段反序列化json

[英]Deserialize json based on fields in .Net (C#)

我正在编写一个应用程序,该应用程序获得了这样的对象的Json列表:

[
   {
       "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 (大小,成本),并从中派生Apple,Melon和Book,然后根据“ ObjectType ”字段对它适合的任何类进行反序列化。 我希望它建立一个ItemToSell对象的列表,每个对象都是Apple,Melon或Book。

如何在.Net中做到这一点?

提前致谢 :)

编辑:我知道如何在Big类中反序列化它可以包含的所有字段,例如: Base(ObjectType,ObjectSize,ObjectCost,ObjectColor,Pages) 但是我希望它通过ObjectType区分类,因此我不会有任何有用的字段,例如每本书的Pages字段或每本书的ObjectTaste

前段时间我遇到了同样的问题。

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

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的转换器中,如下所示:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,

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

您可以使用CustomCreationConverter 这使您可以参与反序列化过程。

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());
    }
}

这不是答案,但是在C#6.0中,您可以执行以下操作:

  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);
    }

这里拍摄

定义基类和派生类。

使用[JSON.net](也可以通过NuGet获得) 1来反序列化它们。

class ItemToSell {
 string Type {get;set;}
 string Size {get;set;}
 string Cost {get;set;}
}

class Book : ItemToSell { ...}

然后反序列化使用

var catalog = JsonConvert.Deserialize<List<ItemToSell>>(json);

解串器将忽略意外的属性。 如果需要,可以使用特定类型再次调用它以获取其他属性。

你的班:

public class RootObject
{
    public string ObjectType { get; set; }
    public int ObjectSize { get; set; }
    public int ObjectCost { get; set; }
    public string ObjectTaste { get; set; }
    public string ObjectColor { get; set; }
    public int? Pages { get; set; }
}

使用NewtonSoft JSON库反序列化如下:

var Jsonobject = JsonConvert.DeserializeObject<RootObject>(json);

看看newtonsoft的JSON库

有了它,您可以执行以下操作:

...
public class Movie
{
   public string Name;
   public DateTime ReleaseDate;
   public string[] Genres;
}
......

string json = @"{
  'Name': 'Bad Boys',
  'ReleaseDate': '1995-4-7T00:00:00',
  'Genres': [
    'Action',
    'Comedy'
  ]
}";

Movie m = JsonConvert.DeserializeObject<Movie>(json);

string name = m.Name;
// Bad Boys

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM