使用Newtonsoft.Json编写自定义JSON转换器

时间:2017-02-05 04:09:48

标签: json list generics deserialization converter

我有一个类结构如下

    public interface IPerson
    {
        string Name { get; set; }
    }
    public class Person : IPerson
    {
        public string Name { get; set; }
    }
    public interface IPersonResult
    {
        List<IPerson> Persons { get; set; }
    }
    public class PersonResult : IPersonResult
    {        
        public List<IPerson> Persons { get; set; }
    }

当我尝试将我的json反序列化为IPersonResult时,如下所示,它给出了错误,

  var personList = new PersonResult
  {
      Persons = new List<IPerson> {new Person {Name = "Jack"}, new Person {Name = "John"}}
  };
  var jsonnn = JsonConvert.SerializeObject(personList);
  var des = JsonConvert.DeserializeObject<PersonResult>(jsonnn);
  

“Type是一个接口或抽象类,无法实例化。”

我使用Newtonsoft库创建了一个自定义JsonConvertor,如下所示,

public class JsonInterfaceConverter<TInterface, TConcrete> :  CustomCreationConverter<TInterface> where TConcrete : TInterface, new()
    {
        public override TInterface Create(Type objectType)
        {
            return new TConcrete();
        }
    }

单个对象可以正常工作,但我需要一个通用的转换器,在反序列化时处理接口列表。

不知何故,这是我努力实现的目标

public class JsonListInterfaceConverter<TInterface, TConcrete> : CustomCreationConverter<IList<TConcrete>> where TConcrete:TInterface 
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.StartArray)
            {
                reader.Read();
                var value = new List<TConcrete>();

                while (reader.TokenType != JsonToken.EndArray)
                {
                    var item = JObject.Load(reader);
                    value.Add(item.ToObject<TConcrete>());
                    reader.Read();
                }
                return value;
            }
            return serializer.Deserialize(reader);
        }
        public override IList<TConcrete> Create(Type objectType)
        {
            return new List<TConcrete>();
        }
    }

可以用作

上的属性
public class PersonResult : IPersonResult
    {
        [JsonConverter(typeof(JsonListInterfaceConverter<Ilist<IPerson>, List<Person>>))]
        public List<IPerson> Persons { get; set; }
    } 

任何帮助?

2 个答案:

答案 0 :(得分:1)

如果没有绑定任何类型的接口

,则无法创建IPerson的列表

为什么你甚至需要PersonResult?只需使用它:

var des = JsonConvert.DeserializeObject<List<Person>>(jsonnn);

此外,这应该适用于您的示例(没有自定义类型绑定器的最简单方法):

var personList = new PersonResult
{
    Persons = new List<IPerson> {new Person {Name = "Jack"}, new Person {Name = "John"}}
};

var serialized = JsonConvert.SerializeObject(personList, Formatting.Indented, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,
    TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple
});

var deserialized = JsonConvert.DeserializeObject<PersonResult>(serialized, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects
});

答案 1 :(得分:0)

这就是我所做的

g.V().has(label,'movies').has('uid',$favoriteMovieNodeId).as('fm')
.addV('Person').property('personId', $personId).addE('favMovie').to('fm')

现在我可以在类

中将其用作IList的属性
 public class JsonListInterfaceConverter<TInterface, TConcrete> : CustomCreationConverter<IList<TConcrete>> where TConcrete:TInterface 
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.StartArray)
            {
                reader.Read();
                var value = new List<TConcrete>();

                while (reader.TokenType != JsonToken.EndArray)
                {
                    var item = JObject.Load(reader);
                    value.Add(item.ToObject<TConcrete>());
                    reader.Read();
                }
                return new List<TInterface>(value.Cast<TInterface>()); //This part I was doing wrong
            }
            return serializer.Deserialize(reader);
        }
        public override IList<TConcrete> Create(Type objectType)
        {
            return new List<TConcrete>();
        }
    }

现在,当我按照以下方式对其进行消毒时,它确实给了我想要的东西

public interface IPerson
{
    string Name { get; set; }
}    
public interface ITask
{
    string TaskName { get; set; }
}
public class Person : IPerson
{
    public string Name { get; set; }
}
public class Task: ITask
{
    public string TaskName { get; set; }
}
public interface IPersonResult
{
    List<IPerson> Persons { get; set; }
}

public class PersonResult : IPersonResult
    {
        [JsonConverter(typeof(JsonListInterfaceConverter<IPerson, Person>))]
        public List<IPerson> Persons { get; set; }

        [JsonConverter(typeof(JsonListInterfaceConverter<ITask, Task>))]
        public List<ITask> Tasks { get; set; }
    }