如何验证我没有收到@JsonProperty 和@JsonAlias 中定义的两个值?

Posted

技术标签:

【中文标题】如何验证我没有收到@JsonProperty 和@JsonAlias 中定义的两个值?【英文标题】:How to validate that I don't receive both values defined in @JsonProperty and @JsonAlias? 【发布时间】:2019-05-26 18:38:03 【问题描述】:

我将实体与孩子呈现为数字child_entity_id。但有时我必须处理 child_entity_selector json 对象,而不是 child_entity_id。用于通过数据库中的某些值提取实体。

父实体有这样的注解

@Entity
class Parent 
    @Id
    long id;

    @JsonDeserialize(using = EntityReferenceDeserializer.class)
    @JsonSerialize(using = EntityReferenceSerializer.class)
    @JsonProperty("child_entity_id")
    @JsonAlias("child_entity_selector")
    Child child;

对于响应json之类的


    "id" : 1,
    "child_entity_id": 1,
    "child_entity_selector": 
        "child_name": "I am a child"
    ,

应该抛出异常,因为只有“child_entity_id”或“child_entity_selector”必须同时在一个json中。

当我收到这样的 json 时,它会正确解析,但我的反序列化器同时处理 child_entity_idchild_entity_selector,最后一个保留在结果中。

目前我正在尝试同时获取源 json 和实体,以检查 json 是否没有被别名覆盖的重复引用。

我已经设置了一个 SimpleModule 和自定义反序列化器

@Component
public class WebConfig 

    @Bean
    public SimpleModule simpleModule() 
        SimpleModule module = new SimpleModule();
        module.setDeserializerModifier(new BeanDeserializerModifier() 
            @Override
            public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) 
                if (beanDesc.getBeanClass() == Child.class)
                    return new ChildDeserializer(deserializer);
                return deserializer;
            
        );
        return module;
    

和反序列化器

public class ChildDeserializer extends StdDeserializer<Child> implements ResolvableDeserializer 
    private final JsonDeserializer<?> defaultDeserializer;

    public ChildDeserializer(JsonDeserializer<?> defaultDeserializer) 
        super(Child.class);
        this.defaultDeserializer = defaultDeserializer;
    

    @Override
    public Child deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException 
        Child modelExecution = (Child) defaultDeserializer.deserialize(p, ctxt);

        // Can not correctly read raw json after parsing -- node becomes null now after deserialization above
        JsonNode node = p.getCodec().readTree(p);

        boolean duplication = node.has("child_entity_id") && node.has("child_entity_selector");
        if (duplication) 
            throw new RuntimeException("Duplicated!")
         else 
            log("Not duplicated");
        
            return child;
    

    @Override
    public void resolve(DeserializationContext ctxt) throws JsonMappingException 
        ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
    


反序列化后,我无法访问 JsonNode 值。反之,解析JsonNode值后无法获得反序列化的Child实体。

预期的行为


    "id" : 1,
    "child_entity_id": 1,


    "id" : 1,
    "child_entity_selector": 
        "child_name": "I am a child"
    ,

是正确解析的实体。

但在两个参考文献中


    "id" : 1,
    "child_entity_id": 1,
    "child_entity_selector": 
        "child_name": "I am a child"
    ,

应该抛出异常。

【问题讨论】:

Only "child_entity_id" or "child_entity_id" is supposed to be presented in one json 很难理解你的意思 @BSeitkazin 改写了它 【参考方案1】:

您可以在 Parent 类中使用 @JsonCreator 处理它

    @JsonCreator
    public Parent(@JsonProperty("child_entity_id") Child childFromId, @JsonProperty("child_entity_selector") Child childFromSelector) 
        if (childFromId != null && childFromSelector != null) 
            throw new RuntimeException("Duplicated!");
        

        this.child = (childFromSelector == null) ? childFromId : childFromSelector;
    

如果您还需要检查重复字段,有一个JsonParser.Feature.STRICT_DUPLICATE_DETECTION


    "id" : 1,
    "child_entity_id": 1,
    "child_entity_id": 2    

不幸的是,它不适用于别名

【讨论】:

是的,它可以根据需要在实体创建中工作。但是,由于 objectMapper.readerForUpdating 导致更新操作失败,出现异常“PatchUpdateException details: No fallback setter/field defined for creator property 'child_entity_ref' (through reference chain: Parent[\"child_entity_ref\"])” 我没有使用更新,听起来@JsonAlias 被忽略了。您可以尝试两个设置子字段的设置器,一个标有@JsonProperty("child_entity_id"),另一个标有@JsonProperty("child_entity_selector")。不过听起来有点邋遢,而且它不会检测到重复项。 当我同时拥有原始 json 和实体类型时,理想的方法是在反序列化时修改 json。从实体类中,我可以提取带有注释的文件并验证|修改实体

以上是关于如何验证我没有收到@JsonProperty 和@JsonAlias 中定义的两个值?的主要内容,如果未能解决你的问题,请参考以下文章

@JsonProperty @JsonIgnoreProperties

使用上下文验证模型

如何在使用自动映射器时将属性名称的 jsonproperty 设置为 dto?

序列化json时如何忽略JsonProperty(PropertyName = "someName")?

@RequestBody 不适用于 @JsonProperty

为啥,我注册软件时没有收到验证码呢?