序列化列表时以JSON显示索引值

时间:2015-01-09 10:55:57

标签: c# json json.net

我有一个包含项目列表的类。当我序列化类时,我希望项目索引值出现在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以输出索引值?

2 个答案:

答案 0 :(得分:2)

尝试使用正确的数据结构,而不是尝试将Json.Net配置为以非标准方式输出数据。作为一个更简单的解决方案,使用Dictionary来存储数组的内容。 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"}
}

答案 1 :(得分:1)

如果您的类中有项目列表但是您需要将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
}