C# JSON.NET 反序列化特定属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19438472/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 14:59:23  来源:igfitidea点击:

JSON.NET deserialize a specific property

c#json.net

提问by Omar

I have the following JSONtext:

我有以下JSON文字:

{
    "PropOne": {
        "Text": "Data"
    }
    "PropTwo": "Data2"
}    

I want to deserialize PropOneinto type PropOneClasswithout the overhead of deserializing any other properties on the object. Can this be done using JSON.NET?

我想反序列PropOne化为类型,PropOneClass而无需反序列化对象上的任何其他属性。这可以使用 JSON.NET 来完成吗?

采纳答案by Matt Johnson-Pint

public T GetFirstInstance<T>(string propertyName, string json)
{
    using (var stringReader = new StringReader(json))
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        while (jsonReader.Read())
        {
            if (jsonReader.TokenType == JsonToken.PropertyName
                && (string)jsonReader.Value == propertyName)
            {
                jsonReader.Read();

                var serializer = new JsonSerializer();
                return serializer.Deserialize<T>(jsonReader);
            }
        }
        return default(T);
    }
}

public class MyType
{
    public string Text { get; set; }
}

public void Test()
{
    string json = "{ \"PropOne\": { \"Text\": \"Data\" }, \"PropTwo\": \"Data2\" }";

    MyType myType = GetFirstInstance<MyType>("PropOne", json);

    Debug.WriteLine(myType.Text);  // "Data"
}

This approach avoids having to deserialize the entire object. But note that this will only improve performance if the json is significantlylarge, and the property you are deserializing is relatively early in the data. Otherwise, you should just deserialize the whole thing and pull out the parts you want, like jcwrequests answer shows.

这种方法避免了反序列化整个对象。但请注意,如果 json非常大,并且您正在反序列化的属性在数据中相对较早,这只会提高性能。否则,您应该反序列化整个内容并拉出您想要的部分,如 jcwrequests 答案所示。

回答by NomadTraveler

Use JsonIgnore- this will cause the property to be completely ignored by Json.Net, both for serializing and deserializing.

使用JsonIgnore- 这将导致 Json.Net 完全忽略该属性,用于序列化和反序列化。

Also, check this link.

另外,请检查此链接

回答by jcwrequests

 var json = "{ "PropOne": { "Text": "Data" } "PropTwo": "Data2" }";

 JObject o = JObject.Parse(json);
 var val = o.PropTwo;

Using JSON Linq provider you do not need to deserialize the object into a known type.

使用 JSON Linq 提供程序,您无需将对象反序列化为已知类型。

回答by Omar

The JSON isn't too large, so I'll take Matt Johnson's suggestion and deserialize the whole thing. Thanks to jcwrequests answer, I was able to use this method:

JSON 并不太大​​,所以我会采纳 Matt Johnson 的建议并反序列化整个内容。感谢 jcwrequests 的回答,我能够使用这个方法:

var jObject = JObject.Parse(json);
var jToken = jObject.GetValue("PropTwo");
PropTwoClass value = jToken.ToObject(typeof(PropTwoClass));

回答by hultqvist

A simpler solution to Omar's answerwould be to have a wrapper.

奥马尔答案的一个更简单的解决方案是使用包装器。

class Wrapper
{
    public PropOneClass PropOne;
}

JsonConvert.Deserialize<Wrapper>(json).PropOne

My tests found it to be about 30% faster.

我的测试发现它快了大约 30%。

回答by hultqvist

Matt's answeris by far the fastest solution though it has a bug. This is my attempt in fixing that. This method will only return a matching property at the root level. There is still a naive approach in counting start and end tokens though for valid JSON it will probably work.

马特的答案是迄今为止最快的解决方案,尽管它有一个错误。这是我试图解决这个问题。此方法将仅返回根级别的匹配属性。尽管对于有效的 JSON 来说它可能会起作用,但在计算开始和结束标记方面仍然有一种天真的方法。

Matt, feel free to copy this into your answer.

马特,请随意将其复制到您的答案中。

public T GetFirstInstance<T>(string propertyName, string json)
{
    using (var stringReader = new StringReader(json))
    using (var jsonReader = new JsonTextReader(stringReader))
    {
        int level = 0;

        while (jsonReader.Read())
        {
            switch (jsonReader.TokenType)
            {
                case JsonToken.PropertyName:
                    if (level != 1)
                        break;
                    if ((string)jsonReader.Value == propertyName)
                    {
                        jsonReader.Read();

                        return (T)jsonReader.Value; 
                    }
                    break;

                case JsonToken.StartArray:
                case JsonToken.StartConstructor:
                case JsonToken.StartObject:
                    level++;
                    break;

                case JsonToken.EndArray:
                case JsonToken.EndConstructor:
                case JsonToken.EndObject:
                    level--;
                    break;
            }

        }
        return default(T);
    }
}