【问题标题】:serialize object with json.net and use jsonignore使用 json.net 序列化对象并使用 jsonignore
【发布时间】:2018-02-07 06:56:05
【问题描述】:

您好,我对 JSON 有疑问。

在 Json.Net 中,我们应该有一个类来序列化类的对象

当我有多个类并且这些类具有一些属性并且我喜欢这样列出一个类时:

public class test
{
    public int id { get; set; }
    public string name { get; set; }
    public string lname { get; set; }
}

 

应该是:

public List<test> get()
{
    test t = new test();
    t.id = 2;
    t.lname = "jahany";
    t.name = "amir";
    return new List<test>() { t };
}

但是,例如,当我有两个类并且我希望拥有这两个具有特定属性的类的列表时,我应该创建一个具有两个类的类的类,例如:

public class test1
{
    public int id { get; set; }
    public string name { get; set; }
}


public class local1
{
    List<test> lst1;
    List<test1> lst2;
    public List<local1> get()
    {
        local1 l = new local1();
        test t = new test();
        t.id = 2;
        t.lname="jahany"
        test1 t1 = new test1();
        t1.name = "amir";
        t.id = 123;
        l.lst1.Add(t);
        l.lst2.Add(t1);
        return new List<local1>(l);
    }
}

 

而且您知道这两个类的所有属性都是 serealise,但我喜欢忽略一些用于序列化的属性,而不是为此创建新类 我该怎么办???

【问题讨论】:

  • 你是怎么解决的?任何答案对您有帮助吗?
  • Ruard van Elburg 没有帮助,当有拖车类并且该类有差异道具时我能做什么,当我想拥有此类的一个列表时,我必须创建一个带有拖车列表的类类
  • 感谢您的评论。我想我了解您的需求并更新了我的答案。如果这是您要找的,请告诉我。

标签: c# json api asp.net-web-api


【解决方案1】:

您可以使用DefaultContractResolver 自定义要忽略的属性:

public class IgnorePropertiesContractResolver<T> : DefaultContractResolver
{
    private IReadOnlyList<string> ignoredProperties;

    public IgnorePropertiesContractResolver(params string[] properties)
    {
        ignoredProperties = properties.ToList();
    }

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

        if (member.DeclaringType == typeof(T) && ignoredProperties.Contains(member.Name))
        {
            property.Ignored = true;
        }

        return property;
    }
}

用法:

var json1 = "{id: 1, name: 'qwe', lname: 'qwe'}";
var json2 = "{id: 2, name: 'asd', lname: 'asd'}";


var ignoreLName = new JsonSerializerSettings
{
     ContractResolver = new IgnorePropertiesContractResolver<test>("lname")
};

var tests = new List<test>();
tests.Add(JsonConvert.DeserializeObject<test>(json1));
tests.Add(JsonConvert.DeserializeObject<test>(json2, ignoreLName));

【讨论】:

    【解决方案2】:

    您可以忽略任何属性。
    标记一下:

    public class test
    {
        public int id { get; set; }
        public string name { get; set; }
        public virtual string lname { get; set; }
    }
    public class test1 : test
    {
      [JsonIgnore]
      public override string lname { get; set; }
    }
    var list = new List<test>()
    {
       new test() {id = 1, name = "name1", lname = "lname1"},
       new test1() {id = 2, name = "name2", lname = "lname2"}
    };
    var s = JsonConvert.SerializeObject(list);
    

    结果:

    [{
        "id": 1,
        "name": "name1",
        "lname": "lname1"
    }, {
        "id": 2,
        "name": "name2"
    }]
    

    【讨论】:

    • 没关系,但是当有两个类并且该类有差异道具时我该怎么办,当我想拥有这些类的一个列表时,我必须创建一个具有类的两个列表的类跨度>
    【解决方案3】:

    我试图理解这个问题。起初我认为这是关于在序列化过程中忽略字段。但是在阅读了您的评论后,我认为这不是问题所在。

    如果我没记错的话,那么您想要序列化一个包含类(test 和 test1)的列表。目前,您正在使用一个对象 (local1) 来包装这两个列表。但是您想要的是一个列表(有或没有对象包装器)。如果我错了,请纠正我。

    我原始答案中的方法序列化为一个列表,但不是混合类。因此,您无法将其还原为混合类列表,因为您没有信息。只有容器类。

    所以你需要的是混合类和维护类信息的东西。

    为此,您可以使用接口:

    public interface baseClass
    {
    }
    

    在两个类中实现接口:

    public class test : baseClass
    {
        public int id { get; set; }
        public string name { get; set; }
        public string lname { get; set; }
    }
    
    public class test1 : baseClass
    {
        public int id { get; set; }
        public string name { get; set; }
    }
    

    并创建列表:

    var lst = new List<baseClass>();
    lst.Add(new test { id = 2, lname = "jahany" });
    lst.Add(new test1 { name = "amir", id = 123 });
    

    现在您需要强制序列化程序添加类型信息,但仅在必要时:

    var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
    var s = JsonConvert.SerializeObject(lst, settings);
    

    其中 s 返回类似:

    [
        {"$type":"test","id":2,"name":null,"lname":"jahany"},
        {"$type":"test1","id":123,"name":"amir"}
    ]
    

    可以反序列化为混合类列表。

    这就是你所追求的吗?

    -- 原始答案--

    您可以使用System.ComponentModel.DefaultValueAttribute。这适用于 xml 和 json。

    这个想法是从序列化输出中省略具有默认值的属性。这将允许您针对不同目的自定义输出,而无需为每个差异创建新模型。在反序列化时,省略的字段应恢复为默认值。

    该值必须与默认值匹配才能被省略。这就是为什么你实际上必须分配一个默认值。

    public class test
    {
        [DefaultValue(0)]
        public int id { get; set; } = 0;
    
        public string name { get; set; }
    
        [DefaultValue(null)]
        public string lname { get; set; } = null;
    }
    

    请注意,name=null 和 lname=null 的结果是一样的。两者都没有序列化。如果为 0,则 id 也会被省略。在反序列化时,id 的值为 0,恰好是 default(int)。

    要在 Json 格式化程序配置中设置这项工作:

    DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate
    

    这将在序列化对象时忽略成员值与成员默认值相同的成员,并在反序列化时将成员设置为其默认值。

    使用方法:

    public List<test> get()
    {
        return new List<test>() { new test
        {
            id = 2,
            lname = "jahany",
            name = "amir"
        } };
    }
    

    要省略 lname,请跳过该字段:

    public List<test> get2()
    {
        return new List<test>() { new test
        {
            id = 2,
            //lname = "jahany",
            name = "amir"
        } };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多