Home > database >  Default Lombok value for Jackson JsonSubTypes mapping
Default Lombok value for Jackson JsonSubTypes mapping

Time:11-01

I want to add boolean field called negate to this class.

@Data
@AllArgsConstructor
@ApiModel
public class RelationEntityTypeFilter {

    @ApiModelProperty(position = 1, value = "Type of the relation between root entity and other entity (e.g. 'Contains' or 'Manages').", example = "Contains")
    private String relationType;

    @ApiModelProperty(position = 2, value = "Array of entity types to filter the related entities (e.g. 'DEVICE', 'ASSET').")
    private List<EntityType> entityTypes;

    @ApiModelProperty(position = 3, value = "Negate relation type between root entity and other entity.")
    private Boolean negate = false;
}

But I got NullPointer on relationEntityTypeFilter.getNegate(), when controller receives such JSON as { "relationType": "Contains", "entityTypes": []}. In other words, negate field should be set to false, but this didn't happen

Here is JsonSubTypes

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "type")
@JsonSubTypes({
        @JsonSubTypes.Type(value = SingleEntityFilter.class, name = "singleEntity"),
        @JsonSubTypes.Type(value = EntityListFilter.class, name = "entityList"),
        @JsonSubTypes.Type(value = EntityNameFilter.class, name = "entityName"),
        @JsonSubTypes.Type(value = EntityTypeFilter.class, name = "entityType"),
        @JsonSubTypes.Type(value = AssetTypeFilter.class, name = "assetType"),
        @JsonSubTypes.Type(value = DeviceTypeFilter.class, name = "deviceType"),
        @JsonSubTypes.Type(value = EdgeTypeFilter.class, name = "edgeType"),
        @JsonSubTypes.Type(value = EntityViewTypeFilter.class, name = "entityViewType"),
        @JsonSubTypes.Type(value = ApiUsageStateFilter.class, name = "apiUsageState"),
        @JsonSubTypes.Type(value = RelationsQueryFilter.class, name = "relationsQuery"),
        @JsonSubTypes.Type(value = AssetSearchQueryFilter.class, name = "assetSearchQuery"),
        @JsonSubTypes.Type(value = DeviceSearchQueryFilter.class, name = "deviceSearchQuery"),
        @JsonSubTypes.Type(value = EntityViewSearchQueryFilter.class, name = "entityViewSearchQuery"),
        @JsonSubTypes.Type(value = EdgeSearchQueryFilter.class, name = "edgeSearchQuery")})
public interface EntityFilter {

    @JsonIgnore
    EntityFilterType getType();
}
@Data
public class RelationsQueryFilter implements EntityFilter {

    @Override
    public EntityFilterType getType() {
        return EntityFilterType.RELATIONS_QUERY;
    }

    private EntityId rootEntity;
    private boolean isMultiRoot;
    private EntityType multiRootEntitiesType;
    private Set<String> multiRootEntityIds;
    private EntitySearchDirection direction;
    private List<RelationEntityTypeFilter> filters;
    private int maxLevel;
    private boolean fetchLastLevelOnly;

}

CodePudding user response:

Using Boolean as a field type doesn't buy you anything, wrapper types are useful for storing in a Collection, and other when you need a reference type (you simply can't use primitive as a generic type in Java, at least for). In all other cases, use a plain primitive boolean, it's much cleaner in the first place because it has only two possible values false and true (false is the default one).

If you change the type of negate from wrapper-type to primitive boolean it would be deserialized as false when the property is missing in the incoming JSON without any extra annotations.

Consider the following simplified class:

@NoArgsConstructor
@Getter
@Setter
@ToString
public static class RelationEntityTypeFilter {
    private boolean negate;
}

Deserialization example:

String negateIsMissing = "{ }";
String negateIsFalse = """
    {
        "negate" : "false"
    }
    """;

ObjectMapper mapper = new ObjectMapper();
    
System.out.println(mapper.readValue(negateIsMissing, RelationEntityTypeFilter.class));
System.out.println(mapper.readValue(negateIsFalse, RelationEntityTypeFilter.class));

Output:

RelationEntityTypeFilter(negate=false)
RelationEntityTypeFilter(negate=false)
  • Related