【问题标题】:problem deserializing object using newtonsoft使用 newtonsoft 反序列化对象的问题
【发布时间】:2022-01-25 17:57:10
【问题描述】:

我希望有人可以帮助我。这是我用来通过 api(在本例中为 Twinkly 灯串)检索有关特定设备的一堆数据的代码。 这是我的部分代码。

            HttpResponseMessage result = await httpClient.GetAsync(uri);
        string response = await result.Content.ReadAsStringAsync();
        JObject jObject = JObject.Parse(response);
        Layout layout = new Layout();
        layout = JsonConvert.DeserializeObject<Layout>(response);

我说它是“部分”功能的,因为根级别中的每个属性都可以很好地反序列化到模型中,但是 json 还返回一个名为“坐标”的属性,该属性由每个灯泡的数组条目和每个条目组成x,y,z 具有三个值。
我已经尝试了很多东西来从坐标数组中获取数据,并且我可以中断模式查看数据在那里。

但是它没有正确反序列化。我在坐标数组中有正确数量的元素,但它们都是 x:0, y:0, z:0

这是我的模型架构。我希望有人可以帮助我。这是我第一次涉足 api 工作,也是我第一次拥有这样的嵌套模型。

 internal class Layout
{ 
    public int aspectXY { get; set; }
    public int aspectXZ { get; set; }
    public LedPosition[] coordinates { get; set; } 
    public string source { get; set; } //linear, 2d, 3d
    public bool synthesized { get; set; }
    public string uuid { get; set; }
}

internal class LedPosition
{
    double x { get; set; }    
    double y { get; set; }
    double z { get; set; }
}

注意:我尝试过像这样手动分配属性:

JToken dataToken = jObject.GetValue("coordinates");

确实收到了数据,但它没有帮助我,因为它只是转移了问题。

【问题讨论】:

  • 公开 x、y 和 z 应该注意它
  • 如果您需要帮助,您必须发布真正的 json,而不是图片。

标签: c# json api json-deserialization


【解决方案1】:

这是我第一次涉足 api 工作

那么我想指出两件事..

  1. 您使用的api是否发布了swagger/open api文档?
    • 否 - 请参阅下面的 2
    • 是的 - 看看 NSwag(Studio)、Autorest 等工具。你将 swagger.json 输入它们,它们会生成几千行代码来创建一个客户端,该客户端执行所有的 http 调用、反序列化、数据类等。如果你的代码最终看起来像这样:
    var client = new TwinklyLightClient();
    var spec = client.GetTwinklyLightSpec();
    foreach(var coord in spec.Coords)
      Console.Write(spec.X);

这就是 API 应有的样子;创建它们的工具按照规则操作,描述它们的工具按照规则操作,因此它们的使用可以通过按照规则操作的工具来完成 - 编写样板 json 和 http 请求正文是计算机的工作,因为它是重复的并且总是遵循相同的模式

  1. API 没有发布我们可以用来让计算机为我们编写无聊部分的规范。杜恩。好吧,您可以自己制作规范(不是那么难),也可以稍微手动一些
    • 获取您的 json(查看原始文件并复制)
    • 访问将 json 转换为代码的众多网站中的任何一个 - 我喜欢 http://QuickType.io,因为它支持多种语言,具有大量自定义功能并提供自定义类型 deser 的高级示例,但还有其他一些 -并将该 json 粘贴到
    • 立即转换为例如 C# 并可以粘贴到您的项目中
    • 它提供了一个示例,说明如何在 cmets 中使用它 - 一个单列,例如:
    var json = httpCallHereTo.GetTheResponseAsJsonString();
    var twinklyLightSpec = TwinklyLightSpec.FromJson(json);

是的,Visual Studio 可以从 json 制作类,但它不是很复杂 - 它可以完成这项工作,但是这些将 json 制作为 c# 的网站更进一步允许您选择数组或列表、根对象的名称,使用 JsonProperty 属性装饰每个属性,该属性指定 json 名称并将 c# 属性保持为 c# 命名约定(或允许您重命名以适合您)..

..它们开箱即用,可以解决您现在遇到的这个问题

【讨论】:

  • 它没有。这是一个隐藏的 api,已被某人检查固件并嗅探灯和应用程序之间的 api 调用进行了逆向工程。
  • 然后使用路线2;从 json 生成 C#
  • 您的信息非常好。 Twinkly 将他们的 api 保密,因为它存在安全漏洞。该应用程序验证它已连接到灯,但灯没有任何方法来验证该应用程序是否合法。登录只需要一个自己生成的密钥,它只是一个序列化的 32 位数字。您必须在同一个网络上,但我们知道它们的安全性。
【解决方案2】:

你不需要同时解析和反序列化,这就足够了

 var response = await result.Content.ReadAsStringAsync();
 var layout = JsonConvert.DeserializeObject<Layout>(response);

为了使 LedPosition 属性可见,也将它们公开

public class LedPosition
{
   public  double x { get; set; }    
   public double y { get; set; }
   public double z { get; set; }
}

因为它被另一个类使用,所以这个类也应该是公共的

public class Layout

【讨论】:

  • 然后使用 JsonProperty 这样我们就不会得到一堆尝起来像 JavaScript 的 C# ?
  • 我的问题是我没有将 ledposition 标记为公开。谢谢你。您会在我发布的代码中注意到未使用该作业。
  • 不客气!
【解决方案3】:

我最近从我工作的大狗 CTO 那里学到的一件事是,您实际上可以复制您期望的 JSON,然后转到编辑 -> 选择性粘贴 -> 将 JSON 粘贴为 Visual Studio 中的类,然后它将其粘贴为您需要的类,并带有正确的名称/属性。真的很滑。也许尝试一下,看看它是否与您现在的模型不同。

【讨论】:

  • 更漂亮的是,有些网站可以生成更好的类,甚至还有 VS 插件的版本
  • 这是一个令人难以置信的提示。谢谢。
  • @Caius Jard 啊,没有意识到这一点。直到最近,我什至不知道 Paste Special 的事情。很高兴知道,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多