【问题标题】:Deserialize JSON into custom c# object list [closed]将 JSON 反序列化为自定义 C# 对象列表 [关闭]
【发布时间】:2021-10-15 12:49:35
【问题描述】:

来自 api 调用:

 var httpClient = new HttpClient();
 var uri = "https://api.postcodes.io/postcodes/";
 var response = await httpClient.PostAsync(uri, data);
 string result = response.Content.ReadAsStringAsync().Result;
 var list = JsonConvert.DeserializeObject<GeoDataList>(result);

有两个自定义类:

  [Serializable]
    public class GeoData
{
    [JsonProperty("postcode")]
    public string postcode { get; set; }

    [JsonProperty("longitude")]
    public string longitude { get; set; }
    [JsonProperty("latitude")]
    public string latitude { get; set; }
}

    public class GeoDataList
    {
        [JsonProperty("result")]
        public List<GeoData> geoDatas { get; set; }
    }

结果包含这个 json 字符串:

{
  "status": 200,
  "result": [{
    "query": "OX49 5NU",
    "result": {
      "postcode": "OX49 5NU",
      "longitude": -1.069876,
      "latitude": 51.6562
    }
  }, {
    "query": "M32 0JG",
    "result": {
      "postcode": "M32 0JG",
      "longitude": -2.302836,
      "latitude": 53.455654
    }
  }, {
    "query": "NE30 1DP",
    "result": {
      "postcode": "NE30 1DP",
      "longitude": -1.439269,
      "latitude": 55.011303,
    }
  }]
}

列表包含 3 个空对象。邮政编码、经度和纬度为空。 如何填充内部对象 (GeoData)?

亲切的问候 /鲁迪

【问题讨论】:

  • 您是否期望所有这 3 个内部 "result"s 最终作为它的直接后代出现在您的一个外部 C# 对象中?您的 C# 类结构未映射到 json 结构..
  • 列表中有2个result属性,在列表的项中,你的模型类显然是错误的
  • @Rudy W check this 示例输出,您的 GeoData 类定义错误,与 json 不匹配。
  • 除了我在下面提到的内容之外,还想让您知道(以防您不知道)现在许多 JSON 发射 API 都有可用的 swagger/openapi 定义;这是一堆 JSON,描述了服务所做的一切、它消耗和发出的所有对象、所有端点的名称等等。为什么这对你来说很有趣?好吧,你可以使用一些工具,比如 NSwagStudio、AutoRest 等,然后对工具说“这里是 swagger/openapi 定义文件”,然后它会字面上为你写 everything ;你会得到一个你使用的客户端类..
  • var c = new PostcodesClient("https://api.postcodes.io"); var result = c.GetLatLong(some_query_data_here); 就是这样,你想要的结果。 NSwag 等人编写了所有的 http 客户端代码,de/ser 代码一切——它使使用 API 就像添加 DLL 引用、创建新对象并调用它的方法一样简单。当你有一个你想要使用的 API 时,尝试找出它的 openapi 端点。在这种情况下,请参阅github.com/ideal-postcodes/openapi

标签: c# json .net


【解决方案1】:

所以,当我们必须使用 JSON 并且我们真的不想手动完成所有这些时,因为它很乏味且容易出错,我们会转到 http://quicktype.io(或 json2csharp,或一些类似的网站)然后我们将我们的 JSON 粘贴到那里..

我们修复了 json 中的任何语法错误(quicktype 在 json-paste 窗口中显示一个红色条),例如最后一个结果纬度上的尾随逗号,我们得到了由 QuickType 生成的这些类:

// <auto-generated />
//
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
//    using SomeNamespace;
//
//    var root = Root.FromJson(jsonString);

namespace SomeNamespace
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class Root
    {
        [JsonProperty("status")]
        public long Status { get; set; }

        [JsonProperty("result")]
        public ResultElement[] Result { get; set; }
    }

    public partial class ResultElement
    {
        [JsonProperty("query")]
        public string Query { get; set; }

        [JsonProperty("result")]
        public ResultResult Result { get; set; }
    }

    public partial class ResultResult
    {
        [JsonProperty("postcode")]
        public string Postcode { get; set; }

        [JsonProperty("longitude")]
        public double Longitude { get; set; }

        [JsonProperty("latitude")]
        public double Latitude { get; set; }
    }

    public partial class Root
    {
        public static Root FromJson(string json) => JsonConvert.DeserializeObject<Root>(json, SomeNamespace.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this Root self) => JsonConvert.SerializeObject(self, SomeNamespace.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters =
            {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

顶部的注释告诉我们如何使用它:

var root = Root.FromJson(jsonString);

然后,如果您只想要内部结果对象,您可以:

root.Result.Select(r => r.Result).ToList()

如果您不喜欢 QT 选择的类名,您可以在 VS 中重构/重命名它们 - json 将保持可解析,因为它还为您添加了所有 [Jsonproeprty] 属性,名称与 JSON 一致所以 C# 道具可以是你喜欢的任何东西

QT 是面向 Newtonsoft 的;如果您想将生成的类与System.Text.Json 一起使用,您只需使用查找/替换和其他一些整理来调整属性名称

我与 QT 的从属关系为零

【讨论】:

  • 或者我们可以在VS中做.... :)
  • 没错,QuickType 确实有一个具有更多功能的 VS 扩展! (戏弄;我偷偷知道^H^H^H^H怀疑你在谈论“将JSON粘贴为类”,但它不会在类型转换器的东西中循环,也不会在ser/deser的便利方法中循环,也不会提供对生成结果的自定义,但它是一个合理的中途之家..)
  • 是的,同意凯厄斯。也可以安装扩展来执行此操作,无需在线转储 json 以获取定义。
  • 完全同意,我只是更乐意推荐“去这个网站,粘贴这个并看看你得到了什么”而不是“如果你只是将这个软件安装到你的 VS ,这可能以管理员身份运行..."。不过值得一提(并在 Q 上的 cmets 中注明)
猜你喜欢
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
  • 1970-01-01
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2022-12-13
相关资源
最近更新 更多