简体   繁体   English

C#Json.Net使用不同的“键”参数反序列化Json

[英]C# Json.Net Deserialize Json with different “key” parameter

I am trying to deserialize JSON using the Json.NET library. 我正在尝试使用Json.NET库反序列化JSON。 JSON which I receive looks like: 我收到的JSON如下所示:

{
    "responseHeader": {
        "zkConnected": true,
        "status": 0,
        "QTime": 2
    },
    "suggest": {
        "mySuggester": {
            "Ext": {
                "numFound": 10,
                "suggestions": [
                    {
                        "term": "Extra Community",
                        "weight": 127,
                        "payload": ""
                    },
                    {
                        "term": "External Video block",
                        "weight": 40,
                        "payload": ""
                    },
                    {
                        "term": "Migrate Extra",
                        "weight": 9,
                        "payload": ""
                    }
                ]
            }
        }
    }
}

The problem is that the "Ext" that you can see in it is part of the parameter passed in the query string and will always be different. 问题在于您可以在其中看到的“ Ext”是在查询字符串中传递的参数的一部分,并且始终是不同的。 I want to get only the values assigned to the term "term". 我只想获取分配给术语“项”的值。

I tried something like this, but unfortunately does not works: 我尝试了类似的方法,但不幸的是它不起作用:

public class AutocompleteResultsInfo
{
    public AutocompleteResultsInfo()
    {
        this.Suggest = new Suggest();
    }
    [JsonProperty("suggest")]
    public Suggest Suggest { get; set; }
}

public class Suggest
{
    [JsonProperty("mySuggester")]
    public MySuggesterElement MySuggesterElement { get; set; }
}

public struct MySuggesterElement
{
    public MySuggester MySuggester;
    public string JsonString;

    public static implicit operator MySuggesterElement(MySuggester MySuggester) =>new MySuggesterElement { MySuggester = MySuggester };
    public static implicit operator MySuggesterElement(string String) => new MySuggesterElement { JsonString = String };
}

public class MySuggester
{
    [JsonProperty("suggestions")]
    public Suggestions[] Suggestions { get; set; }
}

public class Suggestions
{
    [JsonProperty("term")]
    public string Autocopmplete { get; set; }
}

internal class SuggesterElementConverter : JsonConverter
{
    public override bool CanConvert(Type t)
    {
        return t == typeof(MySuggesterElement) || t == typeof(MySuggesterElement?);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case JsonToken.String:
            case JsonToken.Date:
                var stringValue = serializer.Deserialize<string>(reader);
                return new MySuggesterElement { JsonString = stringValue };
            case JsonToken.StartObject:
                var objectValue = serializer.Deserialize<MySuggester>(reader);
                return new MySuggesterElement { MySuggester = objectValue };
        }
        throw new Exception("Cannot unmarshal type MySuggesterElement");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        var value = (MySuggesterElement)untypedValue;
        if (value.JsonString != null)
        {
            serializer.Serialize(writer, value.JsonString);
            return;
        }
        if (value.MySuggester != null)
        {
            serializer.Serialize(writer, value.MySuggester);
            return;
        }
        throw new Exception("Cannot marshal type CollationElements");
    }

    public static readonly SuggesterElementConverter Singleton = new SuggesterElementConverter();
}

public class AutocompleteConverter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters =
        {
            SuggesterElementConverter.Singleton
        }
    };
}

var results = JsonConvert.DeserializeObject<AutocompleteResultsInfo>(resultJson, AutocompleteConverter.Settings);

Many thanks for your help. 非常感谢您的帮助。

Kind Regerds, Wojciech 亲切的问候,Wojciech

You could decode the "mySuggester" as a dictionary: public class Suggest 您可以将“ mySuggester”解码为字典:public class建议

public class Suggest
{
    [JsonProperty("mySuggester")]
    public Dictionary<string, MySuggester> MySuggester { get; set; }
}

Then you'll be able to access the suggestions with the query string parameter: 然后,您可以使用查询字符串参数访问建议:

var variablePropertyName = "Ext";

var result = JsonConvert.DeserializeObject<AutocompleteResultsInfo>(_json);

var suggestions = result.Suggest.MySuggester[variablePropertyName].Suggestions;

if you don't know the property name you could also look it up in the dictionary: 如果您不知道属性名称,也可以在字典中查找它:

var variablePropertyName = result.Suggest.MySuggester.Keys.First();

Working example: https://dotnetfiddle.net/GIKwLs 工作示例: https : //dotnetfiddle.net/GIKwLs

If you don't need to deserialize the whole json string you can use a JsonTextReader. 如果您不需要反序列化整个json字符串,则可以使用JsonTextReader。 Example: 例:

private static IEnumerable<string> GetTerms(string json)
{
    using (JsonTextReader reader = new JsonTextReader(new StringReader(json)))
    {
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.PropertyName && reader.Value.Equals("term"))
            {
                string term = reader.ReadAsString();

                yield return term;
            }
        }
    }
}

Using the code: 使用代码:

string json = @"{
    ""responseHeader"": {
        ""zkConnected"": true,
        ""status"": 0,
        ""QTime"": 2
    },
    ""suggest"": {
        ""mySuggester"": {
            ""Ext"": {
                ""numFound"": 10,
                ""suggestions"": [
                    {
                        ""term"": ""Extra Community"",
                        ""weight"": 127,
                        ""payload"": """"
                    },
                    {
                        ""term"": ""External Video block"",
                        ""weight"": 40,
                        ""payload"": """"
                    },
                    {
                        ""term"": ""Migrate Extra"",
                        ""weight"": 9,
                        ""payload"": """"
                    }
                ]
            }
        }
    }
}";

IEnumerable<string> terms = GetTerms(json);

foreach (string term in terms)
{
    Console.WriteLine(term);
}

If you only need the object containing the term, and nothing else, you could work with the JSON values directly by using the JObject interface in JSON.Net. 如果只需要包含术语的对象,而无需其他,则可以通过使用JObject中的JObject接口直接使用JSON值。

var parsed = JObject.Parse(jsonString);
var usingLinq = (parsed["suggest"]["mySuggester"] as JObject)
    .Descendants()
    .OfType<JObject>()
    .Where(x => x.ContainsKey("term"));

var usingJsonPath = parsed.SelectTokens("$.suggest.mySuggester.*.*[?(@.term)]")
    .Cast<JObject>();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM