使用JSON.NET反序列化对象,但将一些属性放入类的成员中

时间:2015-05-19 21:37:25

标签: c# json serialization json.net

我正在编写一组数据结构,使用JSON.NET将第三方JSON摄取到(无需写出)。

我有一个案例,可以将一些顶级JSON元素读入要反序列化的对象的成员对象中。

我的JSON:

{
    "Id":1
    "Checksum":42
    "Name":"adam",
    "Hair":true
}

我理想的对象结构:

public class EntityHeader
{
    int Id { get; set; }

    int Checksum { get; set; }
}

public class Entity
{
    [HeroicJsonAttribute( "Id", "Checksum" )]
    public EntityHeader Header { get; set; }

    public string Name { get; set; }

    public bool Hair { get; set; }
}

有没有简单的方法来实现这一目标?我将有许多类型需要这个,我不想为每个类型写一个JsonConverter。

之前已经问过这个问题,here,但接受的答案没有解决这个问题。

谢谢!

3 个答案:

答案 0 :(得分:1)

另一种方法是使用Entity类中的EntityHeader字段作为私有属性的后备存储,可以将其反序列化为:

public class EntityHeader
{
    int Id { get; set; }

    int Checksum { get; set; }
}

public class Entity
{
    private EntityHeader m_Header = new EntityHeader();
    public EntityHeader Header { get { return m_Header; } }

    [JsonProperty]
    private int Id { set { m_Header.Id = value; } }

    [JsonProperty]
    private int Checksum { set { m_Header.Checksum = value; } }

    public string Name { get; set; }

    public bool Hair { get; set; }
}

因此,JSON中的所有属性都可以直接读入Entity对象,但Entity对象的使用者可以访问“封装良好”的EntityHeader属性。

我没有对此进行测试,它甚至可能是kludgey,但它在技术上对我有用(OP)。我仍然对其他答案感兴趣!

答案 1 :(得分:1)

根据你的例子,你可以;使用适配器模式:

public class EntityJson
{
  int Id { get; set; }

  int Checksum { get; set; }

  public string Name { get; set; }

  public bool Hair { get; set; }
}

// quick/poor example
public class EntityAdapter : IEntity
{
  public EntityAdapter(EntityJson model)
  {
    Header = new Header(); // and populate this objects fields
    Name = model.Name; // populate other properties
  }

  public EntityHeader Header { get; set; }

  public string Name { get; set; }

  public bool Hair { get; set; }

}

或者滥用json.net忽略不可用的属性的事实:

var entity = JsonConvert.Deserialze<Entity>();
var header = JsonConvert.Deserialize<EntityHeader>();
entity.Header = header;

答案 2 :(得分:1)

我会继续发布这个评论有点太长的答案,所以请把它作为一个扩展评论,而不是实际尝试回答你的具体问题。当然,你最了解你的要求所以这只是我认为的意见:)。

考虑到这一点,我的建议是:

  

不要这样做。

  • 我会创建一个简单的DTO类,它与正在接收的JSON具有1-1的关系;并且我将所有验证属性放在该类的属性上。

  • 一旦我将JSON反序列化为这个简单的DTO,我就会使用某种映射层(自己滚动或使用Automapper等)来映射这个{{ 1}}进入一个更有意义的结构,例如你的DTO类。

  • 我的理由是因为除非你的Entity类本身只是一个简单的DTO(在这种情况下它应该尽可能简单,理想情况下不是复合),你要混合OOP和关注点有数据映射的问题;虽然这本身并不是一件坏事,但它只会增加代码的复杂性。

  • 例如,考虑一下,如果您的传入Entity最终有30或40个属性,并且您设法找出一种方法(可能会根据其他答案调整一些不错的技巧)将其映射到JSON课程。Entity。但是当出现问题时,它会更容易被推理,因此调试,这是一个你可以更加控制的过程;对于奇怪的边缘情况,串行器行为无法帮助你进行特殊调整也会更容易

  • 认为编写和维护这些DTO需要做一些工作,但 很多 - Webtools already does this for you

参考:At the boundaries, Applications are not Object-Oriented