将C#列表序列化为具有内部数组的复数命名对象

将C#列表序列化为具有内部数组的复数命名对象,c#,json,xml,serialization,asp.net-core-2.1,C#,Json,Xml,Serialization,Asp.net Core 2.1,我们有一个遗留的WCF产品,它使用XML序列化属性序列化POCO 下面是一个列表示例,具有XmlArray/XmlArrayItem属性。 有点像[ 现在,我们有了一个.NETCore2.1应用程序,没有XML输出,只有Json。 所以我想将列表序列化到这个Json响应中,这样我就不会破坏任何期待这个响应的客户机 我意识到我可以围绕列表编写一个包装器,但我有大约40个列表要做,调用代码会变得非常模糊。 事实上,如果我执行“粘贴特殊”>“将JSON粘贴为类”,它看起来像: class Mode

我们有一个遗留的WCF产品,它使用XML序列化属性序列化POCO

下面是一个列表示例,具有XmlArray/XmlArrayItem属性。 有点像[

现在,我们有了一个.NETCore2.1应用程序,没有XML输出,只有Json。 所以我想将列表序列化到这个Json响应中,这样我就不会破坏任何期待这个响应的客户机

我意识到我可以围绕列表编写一个包装器,但我有大约40个列表要做,调用代码会变得非常模糊。 事实上,如果我执行“粘贴特殊”>“将JSON粘贴为类”,它看起来像:

  class Model
  {
     public ThingsWrapper Things { get; set; }
  }

    public class ThingsWrapper
    {
        public Thing[] Thing { get; set; }
    }

    public class Thing
    {
...
    }

called with var x = Things.Thing; // (yuck)

基于-我已经尝试过这个JsonConverter。 但结果是这样的,反过来说,我需要对象和数组

{
  "things": [
    {
      "thing": {
        "Id": 1
      }
    },
    {
      "thing": {
        "Id": 2
      }
    }
  ]
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Linq;
公共课程
{
公共静态void Main()
{
var foo=new foo();
foo.Things=newlist{newfoo.Things{Id=1},newfoo.Things{Id=2};
WriteLine(JsonConvert.SerializeObject(foo,Formatting.Indented));
}
}
福班
{
[JsonProperty(“事物”)]
[JsonConverter(typeof(CustomArrayConverter),“thing”)]
公开物品清单
{
得到;
设置
}
公共类事物
{
公共整数Id
{
得到;
设置
}
}
}
类CustomArrayConverter:JsonConverter
{
字符串属性名称
{
得到;
设置
}
公共CustomArrayConverter(字符串属性名称)
{
PropertyName=PropertyName;
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
JArray数组=新的JArray(JArray.Load(reader.Select)(jo=>jo[PropertyName]);
返回array.ToObject(objectType,序列化程序);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
IEnumerable项=(IEnumerable)值;
JArray数组=新的JArray(items.Select(i=>newJobject)(新的JProperty(PropertyName,JToken.FromObject(i,serializer')));
array.WriteTo(writer);
}
公共覆盖布尔CanConvert(类型objectType)
{
//使用[JsonConverter]属性时不调用CanConvert
返回false;
}
}
感谢@Brian on,他为我指明了正确的方向

class CustomArrayConverter<T> : JsonConverter
    {
        string PropertyName { get; set; }

        public CustomArrayConverter(string propertyName)
        {
            PropertyName = propertyName;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JArray array = new JArray(JArray.Load(reader).Select(jo => jo[PropertyName]));
            return array.ToObject(objectType, serializer);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            IEnumerable<T> items = (IEnumerable<T>)value;
            JObject jObject = new JObject(new JProperty(PropertyName, new JArray(items.Select(i => JToken.FromObject(i, serializer)))));
            jObject.WriteTo(writer);
        }

        public override bool CanConvert(Type objectType)
        {
            // CanConvert is not called when the [JsonConverter] attribute is used
            return false;
        }
    }
类CustomArrayConverter:JsonConverter
{
字符串PropertyName{get;set;}
公共CustomArrayConverter(字符串属性名称)
{
PropertyName=PropertyName;
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
JArray数组=新的JArray(JArray.Load(reader.Select)(jo=>jo[PropertyName]);
返回array.ToObject(objectType,序列化程序);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
IEnumerable项=(IEnumerable)值;
JObject-JObject=new-JObject(new-JProperty(PropertyName,new-JArray)(items.Select(i=>JToken.FromObject(i,serializer')));
jObject.WriteTo(writer);
}
公共覆盖布尔CanConvert(类型objectType)
{
//使用[JsonConverter]属性时不调用CanConvert
返回false;
}
}

您可以使用自定义的
JsonConverter
——尽管
CustomCreationConverter
不起作用。问题是内部属性
“Thing”
的名称对于每个列表属性都不同,对吗?它当前由
[XmlArrayItem(字符串名称)]
但是传递给构造函数的名称因属性而异,您打算如何保留该名称?是否继续使用
XmlArrayItem
属性装饰属性?Thing-Internal属性将只设置一次(它是一个Thing数组)。请参阅上面的代码示例2。这不是我选择输出json的方式。但这正是我必须处理的。有没有关于如何使用JsonConverter的示例?谢谢,是的,我做了
  class Model
  {
     public ThingsWrapper Things { get; set; }
  }

    public class ThingsWrapper
    {
        public Thing[] Thing { get; set; }
    }

    public class Thing
    {
...
    }

called with var x = Things.Thing; // (yuck)

{
  "things": [
    {
      "thing": {
        "Id": 1
      }
    },
    {
      "thing": {
        "Id": 2
      }
    }
  ]
}
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class Program
{
    public static void Main()
    {
        var foo = new Foo();
        foo.Things = new List<Foo.Thing>{new Foo.Thing{Id = 1}, new Foo.Thing{Id = 2}};
        Console.WriteLine(JsonConvert.SerializeObject(foo, Formatting.Indented));
    }
}

class Foo
{
    [JsonProperty("things")]
    [JsonConverter(typeof(CustomArrayConverter<Thing>), "thing")]
    public List<Thing> Things
    {
        get;
        set;
    }

    public class Thing
    {
        public int Id
        {
            get;
            set;
        }
    }
}

class CustomArrayConverter<T> : JsonConverter
{
    string PropertyName
    {
        get;
        set;
    }

    public CustomArrayConverter(string propertyName)
    {
        PropertyName = propertyName;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = new JArray(JArray.Load(reader).Select(jo => jo[PropertyName]));
        return array.ToObject(objectType, serializer);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        IEnumerable<T> items = (IEnumerable<T>)value;
        JArray array = new JArray(items.Select(i => new JObject(new JProperty(PropertyName, JToken.FromObject(i, serializer)))));
        array.WriteTo(writer);
    }

    public override bool CanConvert(Type objectType)
    {
        // CanConvert is not called when the [JsonConverter] attribute is used
        return false;
    }
}
class CustomArrayConverter<T> : JsonConverter
    {
        string PropertyName { get; set; }

        public CustomArrayConverter(string propertyName)
        {
            PropertyName = propertyName;
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JArray array = new JArray(JArray.Load(reader).Select(jo => jo[PropertyName]));
            return array.ToObject(objectType, serializer);
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            IEnumerable<T> items = (IEnumerable<T>)value;
            JObject jObject = new JObject(new JProperty(PropertyName, new JArray(items.Select(i => JToken.FromObject(i, serializer)))));
            jObject.WriteTo(writer);
        }

        public override bool CanConvert(Type objectType)
        {
            // CanConvert is not called when the [JsonConverter] attribute is used
            return false;
        }
    }