【问题标题】:Filtering out certain child objects during JSON conversion在 JSON 转换期间过滤掉某些子对象
【发布时间】:2019-01-15 11:18:22
【问题描述】:

我不知道如何用语言解释我们的目标,所以我会直接跳到代码上。

使用我们当前的 json 转换器设置。转换我们的一个事件时,我们得到以下结果。

{
    "PortfolioId": {
        "Id": "portId"
    },
    "EntityId": {
        "Id": "3cf7582b-3cad-4aeb-a671-0132ba97d60d"
    },
    "EventVersion": 1,
    "OccurredOn": "2018-08-08T09:52:03.7871323+02:00",
    "Id": "71fe3a2e-354a-4b19-abea-655471e96d72",
    "Creator": {
        "Id": "27a1d6b1-1ffa-4071-92ee-31c12bf120f0"
    },
    "CorrelationId": "3138dbe0-3a4d-4559-83e9-d1f3e5684ee8"
}

我们的目标是获得如下所示的转换事件;

{
    "PortfolioId": "portId",
    "EntityId":  "3cf7582b-3cad-4aeb-a671-0132ba97d60d",
    "EventVersion": 1,
    "OccurredOn": "2018-08-08T09:52:03.7871323+02:00",
    "Id": "71fe3a2e-354a-4b19-abea-655471e96d72",
    "Creator": "27a1d6b1-1ffa-4071-92ee-31c12bf120f0",
    "CorrelationId": "3138dbe0-3a4d-4559-83e9-d1f3e5684ee8"
}

如果我们有一个特定类型的对象(即EntityIdPortfolioId),它在属性中保存值。所有这些 Id 类型都派生自具有“Id”属性的抽象类。

一个事件类看起来像这样。

 public class ExampleEvent : DomainEvent
{
    public PortfolioId PortfolioId { get; }
    public EntityId EntityId { get;}

    public ExampleEvent(
        PortfolioId portfolioId,
        EntityId entityId,
        UserId creator, Guid correlationId) : base(creator, correlationId)
    {
        PortfolioId = portfolioId;
        EntityId = entityId;
    }
}

有没有人知道如何做到这一点。我认为这可能通过自定义 json 转换器实现,但尚不知道如何在这种情况下实现此功能。

编辑:我应该说这必须通过多种事件类型来完成。而且为了保持低开销,一个通用的可重用解决方案似乎最适合。这意味着最好不要更改事件类本身。 (所以最好没有属性等)

【问题讨论】:

  • @TheGeneral 感谢您的反应。我应该说我们有很多活动。因此,为每个事件构建转换器或包装器并不是很有效。这也会在实现新事件时导致更多开销。
  • 啊,是的,我误解了你想要什么,继续

标签: c# .net serialization json.net deserialization


【解决方案1】:

此答案中的第二种方法可以帮助操纵序列化。 Making a property deserialize but not serialize with json.net

【讨论】:

  • @Read Noor,谢谢您的回复。这可能真的有效。您如何看待他们使用 ContractResolver 的第二个答案。你认为我们可以将它与它们继承的抽象类联系起来吗?
  • @redlum 是的,我认为您可以使用 ContractResolver 来实现。 stackoverflow.com/questions/41088492/… 在这个答案中,使用 Change the contract used for a type 作为指导。
【解决方案2】:

您可以将 JsonIgnore 属性与计算属性一起使用:

public class PortfolioId
{
    public string Id { get; set; }
}

public class EntityId
{
    public string Id { get; set; }
}

public class UserId
{
    public string Id { get; set; }
}

public class ExampleEvent 
{
    private ExampleEvent() // for JSON deserializer
    {
        Creator = new UserId();
        Portfolio = new PortfolioId();
        Entity = new EntityId();
    }

    // add your base constructor call
    public ExampleEvent(PortfolioId portfolio, EntityId entity, UserId creator)
    {
        Creator = creator;
        Portfolio = portfolio;
        Entity = entity;
    }

    [JsonIgnore]
    public UserId Creator { get; set; } 

    public string CreatorId
    {
        get => Creator.Id;
        set => Creator.Id = value;
    }

    [JsonIgnore]
    public PortfolioId Portfolio { get; set; } 

    public string PortfolioId
    {
        get => Portfolio.Id;
        set => Portfolio.Id = value;
    }

    [JsonIgnore]
    public EntityId Entity { get; set; } 

    public string EntityId
    {
        get => Entity.Id;
        set => Entity.Id = value;
    }

    public int EventVersion { get; set; }

    public string Id { get; set; }

    public string CorrelationId { get; set; }
}

【讨论】:

  • 感谢您的回复。然而,这可能会增加很多开销,因为这必须在每个事件中完成,并且会使课程变得混乱。
  • @redlum 这个 JSON 是如何使用的?是用于 API 还是存储?
  • 它用于存储在事件存储中(事件源)
【解决方案3】:

如果JsonIgnore 不能满足您的需求,或者您需要更多定制,您也可以使用JsonProperty.ShouldDeserialize / JsonProperty.ShouldSerialize 寻找IContractResolverhere 一些例子。

【讨论】:

    猜你喜欢
    • 2021-04-13
    • 2012-11-28
    • 2022-08-14
    • 2020-08-22
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多