反序列化嵌套的 json 对象。当内部对象可能不同时

Posted

技术标签:

【中文标题】反序列化嵌套的 json 对象。当内部对象可能不同时【英文标题】:Deserializing nested json objects. When inner object might differ 【发布时间】:2020-09-26 12:54:48 【问题描述】:

我正在处理的服务返回嵌套在通用对象中的不同对象。这是来自服务的示例模型结果

"date":1591430887.591481,"results":["identity":"result_type_a","result":"attr_a":1591427634]
"date":1591430887.591481,"results":["identity":"result_type_b","result":"attr_b":1591427634,"attr_bb":3591457634]
"date":1591430887.591481,"results":["identity":"result_type_c","result":"attr_c":1591427634,"attr_cc":3591457634,"attr_cc":59634,"identity":"result_type_d","result":"attr_d":"rfrvr","attr_dd":"ytur"]

我尝试创建一个将结果属性声明为字符串的通用对象。并计划我可以将返回的 json 反序列化为该通用对象,检查身份属性并将结果属性中的字符串反序列化为特定对象类型。

这是对象结构

public class GeneralResponse

    [JsonProperty("date")]
    public double Date  get; set; 
    [JsonProperty("results")]
    public List<GenericResults> Results  get; set; 



public class GenericResults

    [JsonProperty("identity")]
    public string Identity  get; set; 
    [JsonProperty("result")]
    public string Result  get; set; 

要序列化/反序列化,我使用的是 Newtonsoft 库,代码如下

    public static GeneralResponse SerializeResponse(string response)
    
        return JsonConvert.DeserializeObject<GeneralResponse>(response);
    

不幸的是,我在反序列化通用对象时遇到了以下异常。

“解析值时遇到意外字符:.Path 'results[0].result', line 1, position 71.”

如果我将 GenericResult 的 Result 属性声明为对象,如下所示

public class GenericResults

    [JsonProperty("identity")]
    public string Identity  get; set; 
    [JsonProperty("result")]
    public object Result  get; set; 

我可以通过第一次序列化并进行第二次序列化而不会出现任何异常。

        string inner_object = response.Result.ToString();
        switch (type)
                       
            case ResponseTypes.type_A: return JsonConvert.DeserializeObject<ObjectTypeA>(inner_object);
            case ResponseTypes.type_B: return JsonConvert.DeserializeObject<ObjectTypeB>(inner_object);
            case ResponseTypes.type_C: return JsonConvert.DeserializeObject<ObjectTypeC>(inner_object);
            default: throw new Exception("Unknown Response Type");
        

但返回的对象不包含数据。 我将不胜感激有关对该算法建模的任何帮助。提前致谢。

【问题讨论】:

看起来您的Result 应该是多态类型层次结构。要反序列化这样的类型层次结构,请参阅 Deserializing polymorphic json classes without type information using json.net 和 How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?,这看起来是重复的。同意吗? 【参考方案1】:

当您将string 与 JSON.NET 序列化一起使用时,它实际上并未使用 JSON 字符串,而是尝试解析 JSON 字符串值。

您可以改用 JObject,它是 JSON 对象的 JSON.NETs 包装器。然后,JObject 可用于反序列化为类型或用于直接访问 JSON 属性。像这样:

switch (type)
               
    case ResponseTypes.type_A: return response.Result.ToObject<ObjectTypeA>(inner_object);
    case ResponseTypes.type_B: return response.Result.ToObject<ObjectTypeB>(inner_object);
    case ResponseTypes.type_C: return response.Result.ToObject<ObjectTypeC>(inner_object);
    default: throw new Exception("Unknown Response Type");

【讨论】:

我不知道这个。试过这个,但没有任何区别。还有什么我应该在代码中更改的吗? @Emre 我已经更新了我的答案以包含一个关于如何使用 .ToObject&lt;T&gt; 转换 JObject 的示例。 感谢更新,但没有成功。我猜 inner_object 不应该在那里?【参考方案2】:

您可以使用字典来存储 结果,它看起来是多态的。例如,

   public partial class GeneralResponse
    
        [JsonProperty("date")]
        public double Date  get; set; 

        [JsonProperty("results")]
        public ResultElement[] Results  get; set; 
    

    public partial class ResultElement
    
        [JsonProperty("identity")]
        public string Identity  get; set; 

        [JsonProperty("result")]
        public Dictionary<string,object> Result  get; set; 
    

Working Demo

输出样本

【讨论】:

谢谢,这是个好主意,但对象类型实际上不是字典。我简化了对象以专注于关键部分。

以上是关于反序列化嵌套的 json 对象。当内部对象可能不同时的主要内容,如果未能解决你的问题,请参考以下文章

Json.NET:将嵌套数组反序列化为强类型对象

将JSON对象反序列化为嵌套的C#对象

JSON.net 反序列化对象嵌套数据

Spray-json反序列化嵌套对象

使用嵌套对象中的属性反序列化 JSON [重复]

Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]