序列化列表时在 JSON 中显示索引值

本文关键字:显示 索引值 JSON 列表 序列化 | 更新日期: 2023-09-27 18:36:58

我有一个包含项目列表的类。 当我序列化类时,我希望项目索引值出现在 JSON 中。

我使用以下代码转换为 JSON:

var json = Newtonsoft.Json.JsonConvert.SerializeObject(imp);

现在我得到的输出如下所示:

{
    "userdata":{
        "name":"name",
        "type":"type",
        "company_name":"company_name"
    },
    "f_item":null,
    "o_item":null,
    "attributes":[
        {
            "firstval":"0",
            "name":"at 0",
            "opposite_name":"opname 0"
        },
        {
            "firstval":"1",
            "name":"at 1",
            "opposite_name":"opname 1"
        },
        {
            "firstval":"2",
            "name":"at 2",
            "opposite_name":"opname 2"
        },
        {
            "firstval":"3",
            "name":"at 3",
            "opposite_name":"opname 3"
        },
        {
            "firstval":"4",
            "name":"at 4",
            "opposite_name":"opname 4"
        }
    ],
    "eos":null
}

我需要这样的输出:

{
    "userdata":{
        "name":"name",
        "type":"type",
        "company_name":"company_name"
    },
    "f_item":null,
    "o_item":null,
    "attributes":{
        "0": {
            "firstval":"0",
            "name":"at 0",
            "opposite_name":"opname 0"
        },
        "1": {
            "firstval":"1",
            "name":"at 1",
            "opposite_name":"opname 1"
        },
        "2": {
            "firstval":"2",
            "name":"at 2",
            "opposite_name":"opname 2"
        },
        "3": {
            "firstval":"3",
            "name":"at 3",
            "opposite_name":"opname 3"
        },
        "4": {
            "firstval":"4",
            "name":"at 4",
            "opposite_name":"opname 4"
        }
    },
    "eos":null
}

如何配置 Json.Net 以输出索引值?

序列化列表时在 JSON 中显示索引值

与其尝试将 Json.Net 配置为以非标准方式输出数据,不如尝试使用正确的数据结构。作为一种更简单的解决方案,请使用字典来存储数组的内容。Json.Net 会将其解释为对象,并将每个键用作其属性。

var originalArray = new [] {
    new { Foo = "first",  Bar = "abc" },
    new { Foo = "second", Bar = "def" },
    new { Foo = "third",  Bar = "ghi" },
    new { Foo = "fourth", Bar = "jkl" }
};
var data = originalArray
    .Select((value, index) => new { value, index })
    .ToDictionary(wrapper => wrapper.index, wrapper => wrapper.value);
var json = JsonConvert.SerializeObject(data);

此示例代码将输出以下 JSON,这正是您想要的:

{
    "0": {"Foo":"first",  "Bar":"abc"},
    "1": {"Foo":"second", "Bar":"def"},
    "2": {"Foo":"third",  "Bar":"ghi"},
    "3": {"Foo":"fourth", "Bar":"jkl"}
}

如果类中有项列表,但需要将 JSON 输出格式化为具有索引属性的对象(而不是数组),则可以使用自定义JsonConverter在序列化期间将列表转换为对象。

这是转换器的外观。 这将适用于任何实现ICollection,包括列表和数组。

class ListToObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ICollection).IsAssignableFrom(objectType);
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JObject jo = new JObject();
        int index = 0;
        foreach (object item in (ICollection)value)
        {
            jo.Add(index.ToString(), JToken.FromObject(item, serializer));
            index++;
        }
        jo.WriteTo(writer);
    }
    public override bool CanRead
    {
        get { return false; }
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

若要使用转换器,请将 [JsonConverter] 属性添加到类中的 attributes 属性,如下所示:

    [JsonConverter(typeof(ListToObjectConverter))]
    public List<Attribute> attributes { get; set; }

然后,只需像往常一样序列化,您将获得所需的输出。 这是一个演示:

class Program
{
    static void Main(string[] args)
    {
        RootObject imp = new RootObject
        {
            userdata = new UserData
            {
                name = "name",
                type = "type",
                company_name = "company_name"
            },
            attributes = new List<Attribute>
            {
                new Attribute
                {
                    firstval = "0",
                    name = "at 0",
                    opposite_name = "oppname 0"
                },
                new Attribute
                {
                    firstval = "1",
                    name = "at 1",
                    opposite_name = "oppname 1"
                },
                new Attribute
                {
                    firstval = "2",
                    name = "at 2",
                    opposite_name = "oppname 2"
                }
            }
        };
        var json = JsonConvert.SerializeObject(imp, Formatting.Indented);
        Console.WriteLine(json);
    }
}
public class RootObject
{
    public UserData userdata { get; set; }
    public object f_item { get; set; }
    public object o_item { get; set; }
    [JsonConverter(typeof(ListToObjectConverter))]
    public List<Attribute> attributes { get; set; }
    public object eos { get; set; }
}
public class UserData
{
    public string name { get; set; }
    public string type { get; set; }
    public string company_name { get; set; }
}
public class Attribute
{
    public string firstval { get; set; }
    public string name { get; set; }
    public string opposite_name { get; set; }
}

输出:

{
  "userdata": {
    "name": "name",
    "type": "type",
    "company_name": "company_name"
  },
  "f_item": null,
  "o_item": null,
  "attributes": {
    "0": {
      "firstval": "0",
      "name": "at 0",
      "opposite_name": "oppname 0"
    },
    "1": {
      "firstval": "1",
      "name": "at 1",
      "opposite_name": "oppname 1"
    },
    "2": {
      "firstval": "2",
      "name": "at 2",
      "opposite_name": "oppname 2"
    }
  },
  "eos": null
}