【问题标题】:How to create C# classes to deserialize a JSON string which starts and ends with square brackets如何创建 C# 类以反序列化以方括号开头和结尾的 JSON 字符串
【发布时间】:2020-12-28 03:25:26
【问题描述】:

我从 API 接收到一个 JSON 字符串,并希望将其反序列化为 C# 对象,但无法正确获取类。

我尝试使用http://json2csharp.com/ 创建类,但它无法解析 JSON,但https://jsonlint.com/ 表示 JSON 是有效的。

我也尝试过运行JsonClassGeneratorLib,但它说

无法将 Newtonsoft.Json.Linq.JValue 类型的对象转换为 Newtonsoft.Json.Linq.JObject

这似乎是一个问题,因为 JSON 包含在 [] 方括号中。我相信这是有效的,但会将它变成一个数组。我想我需要在班级的某个地方创建一个数组。

string Json = @"[""error"",{""code"":2,""msg"":""This API Key is invalid""}]";

var obj = JsonConvert.DeserializeObject<RootObject>(Json);


public class CodeMsg
{
    [JsonProperty("code")]
    public long Code { get; set; }

    [JsonProperty("msg")]
    public string Msg { get; set; }
}

public class Result
{
    [JsonProperty("error")]
    public string String { get; set; }
    public CodeMsg cm { get; set; }
}

public class RootObject
{
    public Result Result { get; set; }
}

我总是得到错误

无法将当前 JSON 数组(例如 [1,2,3])反序列化为类型“ConsoleApp1.RootObject”,因为该类型需要 JSON 对象(例如 {"name":"value"})才能正确反序列化。 要修复此错误,请将 JSON 更改为 JSON 对象(例如 {"name":"value"})或将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如 List&lt;T&gt;可以从 JSON 数组反序列化

【问题讨论】:

  • 不能比引用错误消息更好:change the deserialized type to an array or a type that implements a collection interface

标签: c# json json.net


【解决方案1】:

试试这个:

var obj = JsonConvert.DeserializeObject<List<Result>>(Json);

说明:如果 JSON 是一个数组,则 C# RootObject 必须是从 List/IEnumerable 本身派生的,或者您将其反序列化为该类型的 List/Array。

您可以转储您的 RootObject 课程。如果您想使用 RootObject 类型,请使其派生自 List。但这不值得麻烦。

【讨论】:

  • 然后给我这个Error converting value "error" to type 'ConsoleApp1.Result'. Path '[0]', line 1, position 8.
  • 您能否将您的Result 类型括在括号中,以便将其解释为一个连贯的对象? @"[ {""error"",{""code"":2,""msg"":""This API Key is invalid""}}]";
  • 我刚刚意识到你在表达的是一个或类型(我认为你可以称之为有区别的联合):它要么是字符串“error”,要么是对象“CodeMsg”。您无法在 C# 中真正表达这一点。因此我建议使用对象语法。
【解决方案2】:

您的 JSON 是一个包含字符串和对象的异构数组。没有一点帮助,这不会干净地反序列化为强类型的类结构。一种可能的解决方案是使用自定义的JsonConverter,如下所示:

public class ResultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Result);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        Result result = new Result
        {
            String = array[0].Value<string>(),
            cm = array[1].ToObject<CodeMsg>(serializer)
        };
        return result;
    }

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

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

然后使用[JsonConverter] 属性将转换器绑定到您的Result 类,如下所示:

[JsonConverter(typeof(ResultConverter))]
public class Result
{
    public string String { get; set; }
    public CodeMsg cm { get; set; }
}

最后,将 JSON 反序列化为 Result 类,如下所示:

var result = JsonConvert.DeserializeObject<Result>(Json);

工作演示:https://dotnetfiddle.net/RLpm5W

注意:可以删除RootObject类;这里不需要。

【讨论】:

    【解决方案3】:

    请确保您的 json 字符串必须与 JsonHolder 类具有相同的属性。

    public class JsonHolder
    {
        public string Id {get;set;}
        public string Name {get;set;}
        public string Gender {get;set;}
    }
    
    var jsonHolderList = new JsonConvert.DeserializeObject<List<JsonHolder>>(jsonString);
    var jsonHolder = jsonHolderList.Single()
    

    您还可以将 json 字符串转换为 c# 对象作为动态对象。请确保您的 json 字符串必须具有与 JsonHolder 类相同的属性。

    dynamic obj= new JsonConver.DeserializeObject<List<JsonHolder>>(StrJson);
    

    【讨论】:

    • 请确保您的 json 字符串必须具有与 JsonHolder 类相同的属性。
    • 仅代码的答案被认为是低质量的:请务必说明您的代码的作用以及它如何解决问题。我将您的评论移至正文 - 请删除您的评论(我不能)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 2017-02-14
    • 2018-07-11
    • 2020-12-28
    • 1970-01-01
    • 2023-03-19
    • 2018-08-27
    相关资源
    最近更新 更多