1

I have the following Json

    {
    "coreId" : "1",
    "name" : "name",
    "additionalValueList" : [
      {
       "columnName" : "allow_duplicate",
       "rowId"  : "10",
       "value" :  "1"
      },
      {
       "columnName" : "include_in_display",
       "rowId"  : "11",
       "value" :  "0"
      },
      ...e.t.c
     ]
 },
 ...e.t.c

and Java class

class DTO {
@JsonProperty("coreId")
private Integer id;

private String name;

private Boolean allowDuplicate;

private Boolean includeInDisplay;
}

How I can easily map values from 'additionalValueList' to corresponding java fields.For example Json value from field 'columnName' - 'allow_duplicate' = DTO.allowDuplicate. Actually I know how to do it with custom deserializers with @JsonDeserialize annotation and smth like this.Bu I have 40+ DTO and it is not a good idea to create own deserializer for each filed. I am looking for solution to have for example 1 deserializer(since values structure in 'additionalValueList' are the same for all entities) and to pass parameter(field name that I want to map to that field) to custom deserializer that will find in 'additionalValueList' entity with 'column Name' = parameter(that I passed from annotation) and return 'value'. Example

class DTO {
@JsonProperty("coreId")
private Integer id;

private String name;

@JsonDeserialize(using = MyCustDeser.class,param = allow_duplicate)
private Boolean allowDuplicate;

@JsonDeserialize(using = MyCustDeser.class,param = include_in_display)
private Boolean includeInDisplay;
}

It will be a good solution but maybe not easy to achieve.However I will be very grateful for all your advices.Thank you.

1
  • You can not do that at property level. You need to write a generic custom deserialiser for a DTO class and put this logic there. To implement general solution we need more info. How another DTO classes looks like? Do they have the same structure with regular properties and boolean properties which are related with objects in additionalValueList array? Do you have all these DTO classes in one package? Which version of Java do you use? Commented Apr 17, 2020 at 14:36

1 Answer 1

1

Create a Converter class, then specify it on the DTO class.

The following code uses public fields for the simplicity of the example.

/**
 * Intermediate object used for deserializing FooDto from JSON.
 */
public final class FooJson {

    /**
     * Converter used when deserializing FooDto from JSON.
     */
    public static final class ToDtoConverter extends StdConverter<FooJson, FooDto> {
        @Override
        public FooDto convert(FooJson json) {
            FooDto dto = new FooDto();
            dto.name = json.name;
            dto.id = json.coreId;
            dto.allowDuplicate = lookupBoolean(json, "allow_duplicate");
            dto.includeInDisplay = lookupBoolean(json, "include_in_display");
            return dto;
        }
        private static Boolean lookupBoolean(FooJson json, String columnName) {
            String value = lookup(json, columnName);
            return (value == null ? null : (Boolean) ! value.equals("0"));
        }
        private static String lookup(FooJson json, String columnName) {
            if (json.additionalValueList != null)
                for (FooJson.Additional additional : json.additionalValueList)
                    if (columnName.equals(additional.columnName))
                        return additional.value;
            return null;
        }
    }

    public static final class Additional {
        public String columnName;
        public String rowId;
        public String value;
    }

    public Integer coreId;
    public String name;
    public List<Additional> additionalValueList;
}

You now simply annotate the DTO to use it:

@JsonDeserialize(converter = FooJson.ToDtoConverter.class)
public final class FooDto {
    public Integer id;
    public String name;
    public Boolean allowDuplicate;
    public Boolean includeInDisplay;

    @Override
    public String toString() {
        return "FooDto[id=" + this.id +
                    ", name=" + this.name +
                    ", allowDuplicate=" + this.allowDuplicate +
                    ", includeInDisplay=" + this.includeInDisplay + "]";
    }
}

Test

ObjectMapper mapper = new ObjectMapper();
FooDto foo = mapper.readValue(new File("test.json"), FooDto.class);
System.out.println(foo);

Output

FooDto[id=1, name=name, allowDuplicate=true, includeInDisplay=false]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer!It sounds like a good idea, but a problem is, that with this approach I have to create ToDtoConverter for each DTO class.Actually it is not a problem,but I have 40 classes with different field names. So if I will not find any more solutions I will try yours.Thank you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.