【问题标题】:How to deserialize JSON with inconsistent schema如何反序列化具有不一致模式的 JSON
【发布时间】:2017-12-09 16:36:14
【问题描述】:

JavaScript/PHP 老手,.NET 新手。

我正在尝试使用 Json.NET 将从 API 调用返回的 JSON 数据反序列化为某些类实例。

当 JSON 架构一致且与我的类匹配时,它适用于大多数 API 调用。但是,我有一些 JSON 对象会像这样返回:

"searchresult":{ "summary":{
"page":"1 of 451", "relevancy":"100% - 99%", "count":25, "query":"some search query" }, "0":{ "relevance":100, "id":343, }, "1":{ "relevance":99, "id":434, }, "2":{ ... } },

处理不一致架构(如“searchresult”)的最佳方法是什么?

我创建了一个“SearchResult”,它有一个“Summary”属性,但是我不确定如何映射剩余的项目。

【问题讨论】:

  • 当你说它不一致时,你的意思是有不同数量的相关性/ID对吗?否则,如果我们只能看到一件事,就没有什么是不一致的。
  • 可以反序列化成匿名对象。参考这个答案stackoverflow.com/a/33284670/8438534
  • 它认为这是不一致的,因为您有不同数量的积分属性,以及“searchresult”对象内的单个命名属性“summary”。我想使用命名属性“摘要”和一组密钥对项会更好。
  • 谢谢桑迪普。我将使用匿名对象。
  • 您的"searchresults" JSON 包含固定和未知属性名称的混合体。此外,未知属性都是类型化的,即它们的值具有固定的模式。鉴于此,您可以采用How to deserialize a child object with dynamic (numeric) key names? 的方法并使用该答案中实现的[JsonTypedExtensionData]

标签: c# json json.net


【解决方案1】:

为了给你强类型,如果模式总是带有:

  • 总结
  • 不同数量的“相关性”

您可以使用 JsonConverter 类将其反序列化为名为 Summary 的类和“相关性”列表。像这样:

执行:

string json = @"{
    ""searchresult"":{ 
        ""summary"":{

            ""page"":""1 of 451"", 
            ""relevancy"":""100% - 99%"", 
            ""count"":25, 
            ""query"":""some search query"" 
        }, 
        ""0"":{ 
            ""relevance"":100, 
            ""id"":343, 
        }, 
        ""1"":{ 
            ""relevance"":99, 
            ""id"":434, 
        }
    }
}";

var searchResult = JsonConvert.DeserializeObject<SearchResult>(json);

视图模型

[JsonConverter(typeof(Converter))]
class SearchResult
{
    public Summary Summary { get; set; }
    public List<RelevanceWrapper> Relevances { get; set; }
}

class Summary
{
    public string Page { get; set; }
    public string Relevancy { get; set; }
    public int Count { get; set; }
    public string Query { get; set; }
}

class RelevanceWrapper
{
    public int Id { get; set; }
    public int Relevance { get; set; }
}

JsonConverter

class Converter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jObject = JObject.Load(reader);

        var searchResultToken = jObject.GetValue("searchresult");

        var searchResult = new SearchResult()
        {
            Relevances = new List<RelevanceWrapper>()
        };

        foreach (JProperty prop in searchResultToken)
        {
            if (prop.Name == "summary")
            {
                searchResult.Summary = prop.Value.ToObject<Summary>();
            }
            else
            {
                searchResult.Relevances.Add(prop.Value.ToObject<RelevanceWrapper>());
            }
        }

        return searchResult;
    }

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }
}

在 ReadJson 中有更多方法可以做到这一点,以及使用 Json.Net 进行反序列化的其他方法,但我发现这种方法的可读性足以理解发生了什么。

【讨论】:

    猜你喜欢
    • 2015-01-04
    • 2016-07-04
    • 1970-01-01
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    相关资源
    最近更新 更多