使用存储在其中一个属性中的字符串格式的另一个json对象解析json对象

时间:2018-04-12 08:02:51

标签: c# json json.net

我认为我在这里有一个非常独特的问题,我需要利用的API开发人员做了一件我不太了解的事情。但我必须处理它。

最好通过展示一个例子来解释这个问题:

type

我们正在处理一个非常普通的REST API,其中响应是一个json字符串 - 没什么特别的。由于API中有一些抽象,每个响应中都有valuetype字段。 value具有不同的结构化内容,具体取决于value。也没什么特别的。

现在的问题是JsonConvert.DeserializeObject<TargetType>(jsonString)字段中的内容不仅仅是普通的json对象,而是包含 json对象的字符串。因此,json.net的反序列化失败,异常

  

Newtonsoft.Json.JsonSerializationException:转换值时出错   &#34; {&#39; propA&#39;:&#39;类型 - 特定元素&#39;,&#39; propA2&#39;:&#39;另一种类型A   特定元素&#39;}&#34;输入&#39; My.Project.TargetType&#39;。

value库中是否有任何可靠的内置支持来解决这个问题,或者我是否必须采用手动路由并以其他方式修复json或反序列化?

编辑:以提供更多上下文:API确实尝试使用相同的请求和响应来抽象其接口,但我仍然能够在我的代码中请求非常具体的响应。因此,我使用包含公共属性的泛型类和public class Response<TValue> { [JsonProperty("type")] public string Type { get; set; } [JsonProperty("value")] public TValue Value { get; set; } } 的泛型类型,如下所示:

type

事实上,type对我来说甚至不相关,因为我事先知道value我将收到哪些回复(由于我的具体要求)。因此,我也能够确定JsonConvert.DeserializeObject<Response<TargetType>>(jsonString)的响应类型。我的实际反序列化看起来像value

然而,我没有找到一种简洁的方法来解析Response和{{1}}对象。任何建议都非常感谢。

2 个答案:

答案 0 :(得分:1)

不,在您的情况下,您只需要两个步骤:

public class RootObject
{
    public string type {get;set;}
    public string value {get;set;}
}

RootObject r = JsonConvert.DeserializeObject<RootObject>(json);

然后,根据类型,反序列化另一个对象:

if (r.type == "typeA")
{
    TypeA t = JsonConvert.DeserializeObject<TypeA>(r.value);
}

如果所有类型共享一些公共属性,则可以将它们放在接口或基类中。这也可以简化重复使用反序列化的类。

答案 1 :(得分:1)

我自己解决了这个问题,使用了一个在对象本身反序列化后调用方法的内置函数。

public class Response<TValue>
{
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("value")]
    private string ValueString { get; set; }

    public TValue Value { get; set; }

    [OnDeserialized]
    internal void DeserializeValue(StreamingContext context)
    {
        Value = JsonConvert.DeserializeObject<TValue>(ValueString);
    }
}

这样我就可以简单地调用JsonConvert.DeserializeObject<Response<TargetType>>(json),它会首先反序列化Response,然后将value属性反序列化为TargetType