如何在 JSON.NET 中实现自定义 JsonConverter? [英] How to implement custom JsonConverter in JSON.NET?

查看:28
本文介绍了如何在 JSON.NET 中实现自定义 JsonConverter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试扩展此处给出的 JSON.net 示例http://james.newtonking.com/projects/json/help/CustomCreationConverter.html

我有另一个派生自基类/接口的子类

公共类人{公共字符串名字{获取;放;}公共字符串姓氏 { 获取;放;}}公共类员工:人{公共字符串处{get;放;}公共字符串 JobTitle { 获取;放;}}公开课艺术家:人{公共字符串技能{获取;放;}}列表<人>人 = 新列表<人>{新员工(),新员工(),新艺术家(),};

如何将 Json 反序列化回 List

人物 >

<预><代码>[{"部门": "部门1","JobTitle": "JobTitle1","FirstName": "FirstName1","LastName": "LastName1"},{"部门": "部门2","JobTitle": "JobTitle2","FirstName": "FirstName2",姓氏":姓氏 2"},{技能":画家","FirstName": "FirstName3","LastName": "LastName3"}]

我不想使用 TypeNameHandling JsonSerializerSettings.我特别在寻找自定义 JsonConverter 实现来处理这个问题.网络上关于此的文档和示例非常稀少.我似乎无法正确实现 JsonConverter 中重写的 ReadJson() 方法.

解决方案

使用标准的 CustomCreationConverter,我一直在努力研究如何生成正确的类型(PersonEmployee),因为为了确定这一点,您需要分析 JSON,并且没有使用 Create 方法来执行此操作的内置方法.

我找到了一个关于类型转换的讨论线程,结果提供了答案.这是一个链接:类型转换.

所需要的是对 JsonConverter 进行子类化,覆盖 ReadJson 方法并创建一个新的抽象 Create 方法,该方法接受一个 JObject.

<块引用>

JObject 类提供了一种加载 JSON 对象和提供对该对象内数据的访问.

重写的 ReadJson 方法创建一个 JObject 并调用 Create 方法(由我们的派生转换器类实现),传入 JObject 实例.

然后可以分析此 JObject 实例,通过检查某些字段的存在来确定正确的类型.

示例

string json = "[{"部门": "部门1","JobTitle": "JobTitle1","FirstName": "FirstName1","姓氏":"姓氏1"},{"部门": "部门2","JobTitle": "JobTitle2","FirstName": "FirstName2","姓氏":"姓氏2"},{"技能": "画家","FirstName": "FirstName3","LastName": "LastName3"}]";列表<人>人 =JsonConvert.DeserializeObject>(json, new PersonConverter());...公共类 PersonConverter : JsonCreationConverter{protected override Person Create(Type objectType, JObject jObject){如果(FieldExists(技能",jObject)){返回新艺术家();}否则如果(FieldExists(部门",jObject)){返回新员工();}别的{返回新人();}}private bool FieldExists(string fieldName, JObject jObject){返回 jObject[fieldName] != null;}}公共抽象类 JsonCreationConverter;: JsonConverter{///<总结>///创建一个objectType的实例,基于JSON对象中的属性///</总结>///<param name="objectType">预期的对象类型</param>//////将被反序列化的 JSON 对象的内容///</param>///<returns></returns>protected abstract T Create(Type objectType, JObject jObject);public override bool CanConvert(Type objectType){返回 typeof(T).IsAssignableFrom(objectType);}公共覆盖布尔 CanWrite{得到 { 返回假;}}公共覆盖对象 ReadJson(JsonReader reader,类型对象类型,对象现有值,JsonSerializer 序列化器){//从流中加载 JObjectJObject jObject = JObject.Load(reader);//基于JObject创建目标对象T target = Create(objectType, jObject);//填充对象属性serializer.Populate(jObject.CreateReader(), 目标);返回目标;}}

I am trying to extend the JSON.net example given here http://james.newtonking.com/projects/json/help/CustomCreationConverter.html

I have another sub class deriving from base class/Interface

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Employee : Person
{
    public string Department { get; set; }
    public string JobTitle { get; set; }
}

public class Artist : Person
{
    public string Skill { get; set; }
}

List<Person> people  = new List<Person>
{
    new Employee(),
    new Employee(),
    new Artist(),
};

How do I deserialize following Json back to List< Person >

[
  {
    "Department": "Department1",
    "JobTitle": "JobTitle1",
    "FirstName": "FirstName1",
    "LastName": "LastName1"
  },
  {
    "Department": "Department2",
    "JobTitle": "JobTitle2",
    "FirstName": "FirstName2",
    "LastName": "LastName2"
  },
  {
    "Skill": "Painter",
    "FirstName": "FirstName3",
    "LastName": "LastName3"
  }
]

I don't want to use TypeNameHandling JsonSerializerSettings. I am specifically looking for custom JsonConverter implementation to handle this. The documentation and examples around this are pretty sparse on the net. I can't seem to get the the overridden ReadJson() method implementation in JsonConverter right.

解决方案

Using the standard CustomCreationConverter, I was struggling to work how to generate the correct type (Person or Employee), because in order to determine this you need to analyse the JSON and there is no built in way to do this using the Create method.

I found a discussion thread pertaining to type conversion and it turned out to provide the answer. Here is a link: Type converting.

What's required is to subclass JsonConverter, overriding the ReadJson method and creating a new abstract Create method which accepts a JObject.

The JObject class provides a means to load a JSON object and provides access to the data within this object.

The overridden ReadJson method creates a JObject and invokes the Create method (implemented by our derived converter class), passing in the JObject instance.

This JObject instance can then be analysed to determine the correct type by checking existence of certain fields.

Example

string json = "[{
        "Department": "Department1",
        "JobTitle": "JobTitle1",
        "FirstName": "FirstName1",
        "LastName": "LastName1"
    },{
        "Department": "Department2",
        "JobTitle": "JobTitle2",
        "FirstName": "FirstName2",
        "LastName": "LastName2"
    },
        {"Skill": "Painter",
        "FirstName": "FirstName3",
        "LastName": "LastName3"
    }]";

List<Person> persons = 
    JsonConvert.DeserializeObject<List<Person>>(json, new PersonConverter());

...

public class PersonConverter : JsonCreationConverter<Person>
{
    protected override Person Create(Type objectType, JObject jObject)
    {
        if (FieldExists("Skill", jObject))
        {
            return new Artist();
        }
        else if (FieldExists("Department", jObject))
        {
            return new Employee();
        }
        else
        {
            return new Person();
        }
    }

    private bool FieldExists(string fieldName, JObject jObject)
    {
        return jObject[fieldName] != null;
    }
}

public abstract class JsonCreationConverter<T> : JsonConverter
{
    /// <summary>
    /// Create an instance of objectType, based properties in the JSON object
    /// </summary>
    /// <param name="objectType">type of object expected</param>
    /// <param name="jObject">
    /// contents of JSON object that will be deserialized
    /// </param>
    /// <returns></returns>
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

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

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

        // Create target object based on JObject
        T target = Create(objectType, jObject);

        // Populate the object properties
        serializer.Populate(jObject.CreateReader(), target);

        return target;
    }
}

这篇关于如何在 JSON.NET 中实现自定义 JsonConverter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆