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

C# 使用JSON.NET反序列化对象,但将一些属性放入类的成员中,c#,json,serialization,json.net,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; } }

我正在编写一组数据结构,以便使用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

这个问题以前有人问过,但公认的答案并没有回答这个问题


谢谢

另一种方法是使用实体类中的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中的所有属性都可以直接读取到实体对象中,但实体对象的使用者可以访问“良好封装”的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;
var entity=JsonConvert.Deserialze();
var header=JsonConvert.Deserialize();
实体.头=头;

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

有鉴于此,我的建议是:

不要这样做

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

  • 一旦我将
    JSON
    反序列化到这个简单的DTO中,我就会使用某种映射层(滚动您自己的或使用的等)将这个
    DTO
    映射到一个更有意义的结构中,比如您的
    实体

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

  • 例如,如果传入的
    JSON
    最终有30个或40个属性,并且您设法找到了一种方法(可能从其他答案中采用了一些不错的技术)将其映射到
    实体
    类。但是当出现问题时该怎么办呢?对一个你有更多控制权的过程进行推理和调试会容易得多;对于奇数边缘的情况,如果serialiser行为无法帮助您解决问题,那么进行特殊调整也会容易得多

  • 尽管编写和维护这些DTO需要一点工作,但没有那么多-


参考资料:

是否有机会更改JSON源代码(无论是谁生成您的JSON源代码)?@ErikPhilips更改源代码JSON是一种可能性,而且可能很理想,但我想确保在侵犯提供商之前,没有简单的适应方法。反应非常好!让我进行了一些很好的研究,这给了我一些想法,并定义了一些我用直觉大致遵循的惯例。这就是我所说的我的DTO;我想我是想把它弄得太复杂了。也就是说,它们是我们领域空间中的对象,即使我们不直接使用它们。值得将它们具体分开。向前看(这是版本0,“让它运行”),我们将使用专用的解析类型。我会在DTO之前打电话给他们,但我愿意争论。谢谢你的回答@阿里查兹-很高兴这对你有帮助!我认为这项技术的主要优势在于,您正在使用专门的解析技术,从长远来看,这将为您节省大量时间:)谢谢您的回复!我想我们将在下一次迭代中做一个专用的解析对象。关于最后一个概念,我认真考虑了它,但我打算将该模式应用于广泛的对象。由于这些仍在发展中,我想我最好找到一种“少浪费”的方法。再次感谢!我将此标记为答案,因为它最好地解决了尝试的解决方案Y。如果你想以更好的方式解决X问题,请查看下面Stephen和Erik的解决方案。