【问题标题】:Deserialize an object with condition json.net使用条件 json.net 反序列化对象
【发布时间】:2018-11-27 19:17:05
【问题描述】:

我试图弄清楚当每个列表元素都可以具有不同的属性时如何反序列化对象。

例如,假设我必须选择“a”和“b”:

{
  "Email": "james@example.com",
  "CreatedDate": "2013-01-20T00:00:00Z",
  "Roles": [{
    "name": "test",
    "type": "a",
    "town": "xyz"
  },
  {
    "name": "test1",
    "type": "b" 
  }]
}

当有 type == b 时,“town”可以为空或不可见,但当 type == a 时,town 应该是可见的。

我厌倦了使用序列化删除可空字段,但是当我尝试反序列化我的类结构时,只需将“城镇”添加到每个具有空值的元素,这是预期的,因为类结构看起来像那样。类结构应该是怎样的?

【问题讨论】:

  • 你的班级结构现在是什么样子的?您希望它的理想外观如何?
  • 几乎与下面评论中设置的@Connell.O'Donnell 相同。几分钟前,我发表了我真正想要的评论。第一个示例(@Connell.O'Donnell 答案)具有属性 -> 对于您按预期获得的第一个元素,对于第二个元素,我得到 name = test1,type=b,town=null。我试图摆脱元素列表中的这些“town=null”,所以我只有 => name = test1, type=b
  • 您是说对于类型 A,您想使用具有 Town 属性的类,但对于类型 B,您想使用不具有 Town 属性的类?如果是这样,您可以使用自定义 JsonConverter 进行反序列化——请参阅 Deserializing polymorphic json classes without type information using json.net

标签: c# serialization json.net deserialization


【解决方案1】:

如果您使用 Newtonsoft,您可以将 NullValueHandling 标志传递给 JsonProperty 属性。这是他们文档中的一个示例:

https://www.newtonsoft.com/json/help/html/JsonPropertyPropertyLevelSetting.htm

编辑 尝试创建以下对象结构:

public class Person
{
    public string Email { get; set; }
    public DateTime CreatedDate { get; set; }
    public List<Role> Roles { get; set; }
}

public class Role
{
    public string name { get; set; }
    public string type { get; set; }

    [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    public string town { get; set; }
}

然后将该json复制到一个文件中并像这样反序列化

string json = File.ReadAllText("a.json");
Person person = JsonConvert.DeserializeObject<Person>(json);

编辑

好吧,如果您真的根本不想看到该属性,那么您最终会得到一些丑陋的代码。这是一个有效的快速而肮脏的示例。

public class PersonA
{
    public string Email { get; set; }
    public DateTime CreatedDate { get; set; }
    public List<RoleB> Roles { get; set; }       
}

public class RoleB : RoleA
{
    public string town { get; set; }
}

public class PersonB
{
    public string Email { get; set; }
    public DateTime CreatedDate { get; set; }
    public List<RoleA> RolesA { get; set; } = new List<RoleA>();
    public List<RoleB> RolesB { get; set; } = new List<RoleB>();
}

public class RoleA
{
    public string name { get; set; }
    public string type { get; set; }
}

然后做这样的事情:

string json = File.ReadAllText("a.json");
PersonA personA = JsonConvert.DeserializeObject<PersonA>(json);
PersonB personB = new PersonB() { Email = personA.Email, CreatedDate = personA.CreatedDate };

foreach(var role in personA.Roles)
{
    var roleB = role as RoleB;
    if (roleB.town != null)
    {
        personB.RolesB.Add(roleB);
    }
    else
    {
        personB.RolesA.Add(new RoleA() { name = roleB.name, type = roleB.type });
    }
}

【讨论】:

  • 该属性工作正常,直到您尝试反序列化对象。 NullValueHandling 仅用于序列化。正如我所说,在反序列化之后,我仍然在对象中获得具有空值的属性
  • @Superbrain_bug 你不能没有属性。唯一的办法是有两个不同的Role 实现,但是你会遇到一大堆问题,必须先读取json,根据它的值查找一个值,然后决定要反序列化哪个类进入。
  • 我知道我不能使用属性,这就是为什么我要问最好的方法来实现这个
  • @Connell.O'Donnell 具有属性的第一个示例 -> 对于您按预期获得的第一个元素,对于第二个元素,我得到 name = test1,type=b,town=null。我正在尝试摆脱元素列表中的这些“town=null”,所以我只有 => name = test1, type=b 我会尽快尝试第二个示例并让你知道,但我知道它在哪里正在走:(
猜你喜欢
  • 2016-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多