【问题标题】:Deserializing JSON to a class containing a dynamic property with System.Text.Json使用 System.Text.Json 将 JSON 反序列化为包含动态属性的类
【发布时间】:2020-01-28 17:00:17
【问题描述】:

目标是使用 NET Core 3 中的新 System.Text.Json 库将 JSON 响应反序列化为包含动态部分的包装器响应类。

那是

{
    "fixedProperty": "Hello",
    "dynamicProperty": { 
        "attributeOne": "One",
        "attributeTwo": "Two",
    }
}

public class MyResponseClass
{
    public string FixedProperty { get; set; }
    public dynamic DynamicProperty { get; set; }  
}

// Where the dynamic property is one of the classes.
// (MyDataClassOne in the particular JSON example above)
public class MyDataClassOne
{
    public string AttributeOne { get; set; }
    public string AttributeTwo { get; set; }  
}

public class MyDataClassTwo
{
    public string AttributeThree { get; set; }
    public string AttributeFour { get; set; }  
}

...

响应中动态属性的类型总是预先知道的(取决于请求),并且是例如三个不同的类之一。

无法找到一种干净的方法来做到这一点,除了没有一个具有动态属性的包装器类,但每个案例都有多个不同的响应类(这显然工作正常,但不是理想的解决方案)。

编辑: 解决方案是使用泛型。

【问题讨论】:

  • 如果 JSON 不可预测,那么它的意义何在?无论如何,您可以在一个类中拥有所有可能的属性,然后根据哪些属性不为空进行处理……此外,如果您可以控制 JSON,那么也许您应该为您的模型定义更好的策略并具有特定的api 操作返回特定的 JSON 模型。
  • 也许如果您更好地解释应用程序的功能以及您的最终目标是什么,我们可以尝试找出更好的方法来满足您的需求,
  • 我正在使用一个我无法控制的 API。当然,来自该 API 的所有响应都是可预测的。所有响应都具有相同的外部结构和每个端点不同的数据属性。这是我尝试将响应的共同部分分解为练习,我正在自学 C#。正如我所说,为每个响应创建一个单独的模型效果很好,但我正在寻找一种方法来分解常见的外壳。
  • 既然你总是提前知道dynamicProperty的类型,为什么不使用泛型呢? public class MyResponseClass<T> { public string FixedProperty { get; set; } public T DynamicProperty { get; set; } }
  • 是的,如果可行的话,这对我的情况来说是完美的。由于某种原因,如果以这种方式反序列化,DynamicProperty 将保持为空,我不知道为什么。是否支持反序列化为泛型类型?

标签: c# json .net-core-3.0 system.text.json


【解决方案1】:

这样的事情怎么样?

var myResponseClass = new MyResponseClass();

dynamic myClass = JsonSerializer.Deserialize<ExpandoObject>("{\"fixedProperty\":\"Hello\",\"dynamicProperty\": {\"attributeOne\":\"One\",\"attributeTwo\":\"Two\"}}");
dynamic myProperty = JsonSerializer.Deserialize<ExpandoObject>(myClass.dynamicProperty.ToString());

myResponseClass.FixedProperty = myClass.fixedProperty.ToString();
myResponseClass.DynamicProperty = myProperty;

【讨论】:

  • 感谢您的回复!尽管使用泛型类型更适合我的场景,但这实际上回答了我想问的另一个问题!谢谢。
【解决方案2】:

由于响应中动态属性的类型总是提前知道的(取决于请求),你可以使用generic根对象:

public class MyResponseClass<T> 
{ 
    public string FixedProperty { get; set; } 
    public T DynamicProperty { get; set; } 
}

然后将T 声明为所需的任何已知具体类,例如

var root = JsonSerializer.Deserialize<MyResponseClass<MyDataClassOne>>(responseString);
var fixedProperty = root.fixedProperty;
var attributeOne = root.DynamicProperty?.AttributeOne;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-22
    相关资源
    最近更新 更多