如何转换为JSON字符串列表,当一些JSON对象是字符串,有些是数组? [英] How to convert JSON to list string, when some of the JSON objects are string and some are array?

查看:232
本文介绍了如何转换为JSON字符串列表,当一些JSON对象是字符串,有些是数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的JSON的样子

{
"d": {
"__type": "CubeJsonData",
"SessionID": null,
"Code": 0,
"Message": "",
"Rows": {},
"Columns": {
  "Place 1": [
    0,
    1
  ],
  "Place 2": [
    0,
    2,
    4,
    6
  ],
},
"Set": [
  [
    "Number 1"
  ],
  [
    "Number 2"
  ],
  [
    "Number 3"
  ]
]
}
}

我需要得到以下值

I need to get the following values

List<string> Columns must contain: "Place 1", "Place 2"
List<string> Set must contain: "Number 1", "Number 2", "Number 3"

我来电是

var settings = new JsonSerializerSettings();
settings.Converters.Add(new AssosiativeArrayConverter());
var staffAlerts = JsonConvert.DeserializeObject<List<AlertDetails>>(jo.ToString(), settings);

我的JsonConverter是

My JsonConverter is

class AssosiativeArrayConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(string)) || (objectType == typeof(List<string>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            var l = new List<string>();
            reader.Read();
            while (reader.TokenType != JsonToken.EndArray)
            {
                l.Add(reader.Value as string);

                reader.Read();
            }
            return l;
        }
        else
        {
            return new List<string> { reader.Value as string };
        }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {//to do
    }
}

我的类

class StaffDetail
{
    public string __type { get; set; }
    public string SessionID { get; set; }
    public string Code { get; set; }
    public string Message { get; set; }

    [JsonConverter(typeof(AssosiativeArrayConverter))]
    public List<string> Rows { get; set; }
    [JsonConverter(typeof(AssosiativeArrayConverter))]
    public List<string> Columns { get; set; }
    [JsonConverter(typeof(AssosiativeArrayConverter))]
    public List<string> Set { get; set; }
}

我得到一个错误

I am getting an error

无法反序列化的当前JSON对象(例如{名:值})入式'System.Collections.Generic.List`1 [ReportingServicesAlerts.AlertDetails],因为该类型需要一个JSON阵列(例如[1 ,2,3]),以正确的反序列化。   要解决这个错误要么改变的JSON到一个JSON阵列(例如[1,2,3])或更改反序列化的类型,以便它是一个正常的.NET类型(例如,不是一个原始类型的整数一样,并不像一个集合类型数组或列表),可以从一个JSON对象反序列化。 JsonObjectAttribute也可以加入到类型迫使它从JSON对象反序列化

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ReportingServicesAlerts.AlertDetails]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

你能不能帮我找出我在做什么错了?

Can you help me figure out what I'm doing wrong?

推荐答案

您有很多问题会在这里。让我先谈谈您收到此错误的原因:你的JSON包含一个外部对象,但你试图反序列化到一个列表。这将无法正常工作。如果有只是一个单一的对象在JSON,你需要反序列化到一个单一的对象。

You have a lot of problems going on here. Let me start with the reason you are getting this error: your JSON contains a single outer object, but you are trying to deserialize it into a list. This won't work. If there's just a single object in the JSON, you need to deserialize into a single object.

第二期,为你的 StaffDetail 类中的数据是不是在你的JSON的顶层;它是在 D 外JSON对象的属性值,一级down--。为了解决这个问题,就需要引入一个包装类和反序列化到这一点。然后你就可以从包装中检索 StaffDetail

Second issue, the data for your StaffDetail class is not at the top level of your JSON; it is one level down-- in the value of the d property of the outer JSON object. To fix this, you need to introduce a wrapper class and deserialize into that. Then you can retrieve the StaffDetail from the wrapper.

第三个问题,它看起来像你试图压平设置从JSON数据为名单,其中,串&GT; 属性在您的类。看起来你已经正确地认识到,你需要一个转换器来做到这一点;然而,你的转换器不处理JSON数据correctly--它是假设它是会得到字符串只是一个简单的数组或一个简单的字符串。无论是设置的结构是这样的JSON,此外,数据结构不同的两种他们。前者是含有属性,它们的值是整数的阵列的对象。后者是一个字符串数组的数组。因为它们是不同的结构,它们需要不同的处理。我建议使用两个不同的转换器在这种情况下

Third issue, it looks like you are trying to flatten the Columns and Set data from the JSON into List<string> properties in your class. It looks like you have correctly realized that you need a converter to do this; however, your converter doesn't handle the JSON data correctly-- it is assuming it is going to get just a simple array of strings or a simple string. Neither Columns nor Set is structured in this way in the JSON, and furthermore, the data is structured differently for both of them. The former is an object containing properties whose values are arrays of integers. The latter is an array of arrays of strings. Since they are different structures, they need to be handled differently. I would suggest using two different converters in this case.

第四,当你正确地装饰你的 StaffDetail 类[JsonConverter] 属性来表明哪些属性应该用你的转换器,你还错误地将转换器加到串行设置。这样做的问题是,你的转换器说,在 CanConvert ,它可以处理任何字符串或字符串的任何列表。如果你申请的转换器,这意味着Json.Net将尝试使用转换器的任何财产的任何地方是一个字符串或字符串列表的设置。显然,你不想this--你的转换器真的打算只是为了处理一个特殊情况。

Fourthly, while you correctly decorate your StaffDetail class with [JsonConverter] attributes to indicate which properties should use your converter, you incorrectly also add the converter to the serializer settings. The problem with this is that your converter says in CanConvert that it can handle any string or any list of strings. If you apply the converter in the settings that means that Json.Net will try to use your converter for any property anywhere that is either a string or a list of strings. Clearly, you do not want this-- your converter is really intended just to handle one specific case.

五,看起来你还装饰了你的属性与 [JsonConverter] 属性,但JSON显示一个空的对象。请问这个领域有你关心的数据?如果没有,只是声明为对象;如果你做护理,请出示一下可能是在那里的一个例子。或者,如果你知道,这将是结构相同,无论是设置,那么你可以把它作为名单,其中,串&GT; 和重用这些转换器之一

Fifth, it looks like you have also decorated your Rows property with a [JsonConverter] attribute, but the JSON shows an empty object. Will this field have any data that you care about? If not, just declare it as object; if you do care, please show an example of what might be in there. Or if you know that it will be structured the same as either Columns or Set, then you can keep it as List<string> and reuse one of those converters.

也有在你的问题其他一些小问题,比如你的JSON是无效的,由于额外的逗号(已经指出的@frno),而事实上,您的来电 JsonConvert.DeserializeObject( )提到了一个名为 AlertDetails ,但您展示类实际上被命名为 StaffDetail 。但是,我们将粉笔那些高达简单的复制粘贴错误。

There are also some other minor issues in your question such as your JSON being invalid due to an extra comma (already pointed out by @frno), and the fact that your call to JsonConvert.DeserializeObject() mentions a class called AlertDetails but the class you show is actually named StaffDetail. But we'll chalk those up to simple copy-paste mistakes.

呼!

确定,那么,我们如何解决这一切?

让先从你的类。我提到你需要一个包装类,因为你的数据实际上是下一层的JSON;这里,将是什么样子:

Let start with your classes. I mentioned that you need a wrapper class since your data is actually one level down in the JSON; here's what that would look like:

class Wrapper
{
    public StaffDetail d { get; set; }
}

有关你的 StaffDetail 类,我已经修改了设置属性使用不同的转换器,因为JSON是针对每个不同。我将在后面解释这些转换器。我也改变了行类型对象,并删除了 [JsonConverter] 属性现在,因为它不是从如何那场应该如何处理的问题清晰。如果数据的结构将类似于设置则可以将其改回,并使用相应的转换器,因为我提及。

For your StaffDetail class, I've changed the Columns and Set properties to use different converters, since the JSON is different for each. I'll define those converters next. I also changed the type of Rows to object and removed the [JsonConverter] attribute for now, since it's not clear from the question how that field should be handled. If the data will be structured like Columns or Set then you can change it back and use the appropriate converter, as I mentioned.

class StaffDetail
{
    public string __type { get; set; }
    public string SessionID { get; set; }
    public string Code { get; set; }
    public string Message { get; set; }
    public object Rows { get; set; }

    [JsonConverter(typeof(ColumnsConverter))]
    public List<string> Columns { get; set; }

    [JsonConverter(typeof(SetConverter))]
    public List<string> Set { get; set; }
}

下面是转换器,它会处理数据。该转换器将一个JSON对象并提取属性名称为字符串列表。

Here is the converter which will handle the Columns data. This converter will take a JSON object and extract the property names into a list of strings.

class ColumnsConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // this converter can handle converting some JSON to a List<string>
        return objectType == typeof(List<string>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Convert an object to a flat list of strings containing
        // just the property names from the object.
        JObject obj = JObject.Load(reader);
        return obj.Properties().Select(p => p.Name).ToList();
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

下面是转换器,它会处理设置数据。该转换器将字符串数组的数组,并把它转换成字符串的平面列表。

Here is the converter which will handle the Set data. This converter will take an array of arrays of strings and convert it into a flat list of strings.

class SetConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // this converter can handle converting some JSON to a List<string>
        return objectType == typeof(List<string>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Convert an array of arrays of strings to a flat list of strings
        JArray array = JArray.Load(reader);
        return array.Children<JArray>()
            .SelectMany(ja => ja.Children(), (ja, jt) => jt.Value<string>()).ToList();
    }

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

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

要反序列化,你可以叫 JsonConvert.DeserializeObject()这样的。请注意,我是如何反序列化到包装类,然后检索 StaffDetail 从它。还要注意,我不需要(并且不应该在这种情况下)通过转换器到解串行器。他们将获得自动获取,并在适当的时候凭借 [JsonConverter] StaffDetail 类属性属性

To deserialize, you can call JsonConvert.DeserializeObject() like this. Notice how I deserialize into the Wrapper class, then retrieve the StaffDetail from it. Also notice that I don't need to (and shouldn't in this case) pass the converters to the deserializer. They will get picked up automatically and at the appropriate times by virtue of the [JsonConverter] attributes on the StaffDetail class properties.

StaffDetail detail = JsonConvert.DeserializeObject<Wrapper>(json).d;

下面是简单的演示程序,以显示它是如何工作的:

Here is simple demo program to show how it all works:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""d"": {
                ""__type"": ""CubeJsonData"",
                ""SessionID"": null,
                ""Code"": 0,
                ""Message"": """",
                ""Rows"": {},
                ""Columns"": {
                    ""Place 1"": [
                        0,
                        1
                    ],
                    ""Place 2"": [
                        0,
                        2,
                        4,
                        6
                    ]
                },
                ""Set"": [
                    [
                        ""Number 1""
                    ],
                    [
                        ""Number 2""
                    ],
                    [
                        ""Number 3""
                    ]
                ]
            }
        }";

        StaffDetail detail = JsonConvert.DeserializeObject<Wrapper>(json).d;

        Console.WriteLine("Columns: " + string.Join(", ", detail.Columns));
        Console.WriteLine("Set: " + string.Join(", ", detail.Set));
    }
}

输出:

Columns: Place 1, Place 2
Set: Number 1, Number 2, Number 3

这篇关于如何转换为JSON字符串列表,当一些JSON对象是字符串,有些是数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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