C# 反序列化期间 JSON.Net 忽略属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12754463/
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 00:19:43  来源:igfitidea点击:

JSON.Net Ignore Property during deserialization

c#jsonjson.net

提问by FEXTWOLF

I have a class set up as follows:

我有一个类设置如下:

public class Foo
{
    public string string1 { get; set; }
    public string string2 { get; set; }
    public string string3 { get; set; }
}

I am using Json.Net to deserialize the following Json Response:

我正在使用 Json.Net 反序列化以下 Json 响应:

string json = "[{\"number1\": 1, \"number2\": 12345678901234567890, \"number3\": 3},      
{\"number1\": 9, \"number2\": 12345678901234567890, \"number3\": 8}]";

Deserialization code:

反序列化代码:

List<Foo> foos = JsonConvert.DeserializeObject<List<Foo>>(json);

The second number exceeds an int-64, but I don't really care about retrieving that value. Is there a way to cast the 'number2' property to a string, or fully ignore it during deserialization?

第二个数字超过了 int-64,但我并不真正关心检索该值。有没有办法将“number2”属性转换为字符串,或者在反序列化过程中完全忽略它?

I have tried adding the [JsonConverter(typeof(string))]attribute to the string2 property, but recieve the error: Error creating System.String. I have also tried setting typeof(decimal).

我曾尝试将该[JsonConverter(typeof(string))]属性添加到 string2 属性,但收到错误:Error creating System.String。我也试过设置typeof(decimal)

I have also tried using [JsonIgnore]but that doesn't work.

我也试过使用,[JsonIgnore]但不起作用。

回答by Dharun

This is a lame workaround but you could make a method to manually load the json. If it's too much data to load without an automatic deserializer just remove the nodes that you don't want. This is a lot slower though.

这是一个蹩脚的解决方法,但您可以创建一种方法来手动加载 json。如果在没有自动解串器的情况下加载太多数据,只需删除您不想要的节点。不过这要慢很多。

public static List<Foo> FromJson(string input) {
    var json = JToken.Parse(input);
    json["key"].Remove();
    var foo = JsonConvert.DeserializeObject<List<Foo>>(json.ToString());

}

This is an interesting problem I wonder if anyone has a better solution for it.

这是一个有趣的问题,我想知道是否有人有更好的解决方案。

回答by Florin D. Preda

You can use MissingMemberHandlingproperty of the JsonSerializerSettingsobject.

您可以使用对象的MissingMemberHandling属性JsonSerializerSettings

Example usage:

用法示例:

var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

JsonConvert.DeserializeObject<YourClass>(jsonResponse, jsonSerializerSettings);

More info here.

更多信息在这里

回答by Maslow

Here's the Newtonsoft Json preferred way to ignore a property without having to modify the class as based on http://james.newtonking.com/json/help/index.html?topic=html/ReducingSerializedJSONSize.htm

这是忽略属性的 Newtonsoft Json 首选方法,而无需根据http://james.newtonking.com/json/help/index.html?topic=html/ReducingSerializedJSONSize.htm修改类

This one is used to ignore lazy reference properties of EF or Linq2Sql

这个是用来忽略EF或者Linq2Sql的惰性引用属性的

public class DynamicContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, 
        MemberSerialization memberSerialization)
    {
        Func<Type,bool> includeProperty = t => t.IsValueType || t.Namespace.StartsWith("System") && t.Namespace.StartsWith("System.Data")==false; 
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        var allProperties = properties.Select (p => new{p.PropertyName,Including=includeProperty(p.PropertyType), p.PropertyType});//.Dump("props");
        var warnProperties=allProperties.Where (a =>a.Including && a.PropertyType.IsValueType==false && a.PropertyType.Name.IsIgnoreCaseMatch("String")==false) ;

        //linq pad debugging helper
        //var propertyTypesSerializing= allProperties.Where (p => p.Including).Select (p => p.PropertyType).Distinct().OrderBy (p => p.Name).Dump();

        if(warnProperties.Any())
        {
            //LinqPad helper
            //Util.Highlight(warnProperties.ToArray()).Dump("warning flag raised, aborting");
            throw new ArgumentOutOfRangeException();
        }

        properties = properties.Where(p =>includeProperty(p.PropertyType)).ToList();
        return properties;
    }
}

All the .Dump()calls are just linqpad debugging helpers, not needed method calls.

所有的.Dump()调用都只是 linqpad 调试助手,不需要方法调用。

sample usage:

示例用法:

var inactives = from am in Aspnet_Memberships
        join mm in Member_members on am.UserId equals mm.Member_guid
        where mm.Is_active==false && mm.Org_id==1
        select new{am,mm};
        //inactives.Take(4).ToArray().Dump();
        var serialized = JsonConvert.SerializeObject(
            inactives.Skip(1).Select(i => i.mm).First(), 
            new  JsonSerializerSettings()
            {
                ContractResolver = new DynamicContractResolver(), 
                PreserveReferencesHandling = PreserveReferencesHandling.None,
                ReferenceLoopHandling= ReferenceLoopHandling.Ignore
            }); 
            //.Dump();

回答by drzaus

Similar to @Maslow's solution, you can use another general purpose "ignorer":

@Maslow的解决方案类似,您可以使用另一个通用“忽略程序”

var jsonResolver = new IgnorableSerializerContractResolver();
// ignore your specific property
jsonResolver.Ignore(typeof(Foo), "string2");
// ignore single datatype
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };

回答by Ohad Bitton

Adding to drzaus answer: You can use the DefaultContractResolverhe suggested .. just in its CreatePropertyuse property.Ignored = true;instead of property.ShouldSerialize, then its good either when you pass the JsonSerializerSettingsto the DeserializeObjectfunction or the SerializeObjectfunction.

添加到 drzaus 答案:您可以使用DefaultContractResolver他建议的 .. 只是在其CreateProperty使用中property.Ignored = true;而不是property.ShouldSerialize,那么当您将 传递JsonSerializerSettingsDeserializeObject函数或SerializeObject函数时它都很好。

回答by dcansyn

Alternative;

选择;

If ResponseAttribute has in model or string parameters

如果 ResponseAttribute 具有模型或字符串参数

public class ResponseAttribute : Attribute { }

public class ModelItem
{
    [Response]
    public Guid Id { get; set; }
}

Code;

代码;

public class CustomJsonSerializer : JsonSerializerSettings
{
    public CustomJsonSerializer()
    {
        ContractResolver = new CustomContractResolver();
    }

    public CustomJsonSerializer(params string[] members)
    {
        ContractResolver = new CustomContractResolver(members);
    }

    public class CustomContractResolver : DefaultContractResolver
    {
        public string[] Members { get; set; }
        public CustomContractResolver(params string[] _members)
        {
            Members = _members;
        }

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);

            if (Members?.Length > 0)
                property.ShouldSerialize = instance => { return Members.Contains(member.Name); };
            else
                property.ShouldSerialize = instance => { return member.GetCustomAttribute<ResponseAttribute>() != null; };

            return property;
        }
    }
}

Use;

用;

return new JsonResult(model, new CustomJsonSerializer());

or

或者

return new JsonResult(model, new CustomJsonSerializer("Id","Test","Test2"));