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

Deserialize object using JSON.NET, but put some properties into a member of the class

我正在编写一组数据结构以使用 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,但接受的答案没有解决这个问题。

谢谢!

另一种方法是使用实​​体 class 中的 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 对象的消费者可以访问 "nicely encapsulated" EntityHeader 属性.

我还没有测试过这个,它甚至可能有点笨拙,但它在技术上对我有用 (OP)。我仍然对其他答案感兴趣!

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

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;

我要继续 post 这个答案对于评论来说有点太长了,所以请更多地把它当作一个扩展评论,而不是实际尝试回答你的具体问题。当然,您最了解自己的要求,所以这只是我考虑过的意见 :)

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

Don't do this.

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

  • 一旦我将 JSON 反序列化为这个简单的 DTO,我就会使用某种映射层(滚动你自己的或使用 Automapper 等)来将此 DTO 映射到更有意义的结构中,例如您的 Entity class.

  • 我的理由是,除非你的 Entity class 本身只是一个简单的 DTO(在这种情况下,它应该尽可能简单,最好不是复合材料)您正在混合 OOP 和关注点与数据映射关注点;虽然这本身并不是一件坏事,但它只会增加代码的复杂性。

  • 例如,考虑一下如果您传入的 JSON 最终有 30 或 40 个属性,并且您设法想出了一个方法(也许采用其他答案中的一些不错的技术)将其映射到 Entity class。但是,当出现问题时怎么办 - 它会变得 更容易 推理,因此调试一个您可以更好地控制的过程;对于序列化器行为无法帮助您解决问题的奇数边缘情况进行特殊调整也会变得容易得多

  • 虽然编写和维护这些 DTO 需要一些工作,但 并不多 - Webtools already does this for you

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