2

I want to deserialize this json as Map<string, LocalizationDto>:

{
    "DE": {
        "name": "name1",
        "description": "name1 description"
    },
    "EN": {
        "name": "name2",
        "description": "name2 description"
    }
}

that represents the parameter "localizations" in this Request Dto:

@Getter
@Setter
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@AllArgsConstructor
public class RequestDto {

    @Size(max = 16)
    @NotEmpty
    private String code;

    @NotNull
    private Boolean stackable;

    @NotNull
    private MultipartFile file;

    
    @JsonDeserialize(using = MapDeserializer.class )
    @JsonProperty("localizations")
    @NotEmpty
    private Map<String, LocalizationDto> localizations;

    @JsonCreator
    public RequestDto() {
    }


    public static class MapDeserializer extends JsonDeserializer <Map<String, LocalizationDto>> {

        public MapDeserializer() {
            super();
        }

        @Override
        public Map<String, LocalizationDto> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
                throws IOException {
            ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
            if (jsonParser.getCurrentToken().equals(JsonToken.START_OBJECT)) {
                return mapper.readValue(jsonParser, new TypeReference<>() {
                });
            } else {
                //consume this stream
                mapper.readTree(jsonParser);
                return new HashMap<>();
            }
        }
    }
}

The LocalizationDto class is:

@Getter
@Setter
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
@NoArgsConstructor
@AllArgsConstructor
public class LocalizationDto {

    @NotBlank
    @Size(max = 1024)
    public String name;

    @NotBlank
    @Size(max = 1024)
    public String description;
}

the Deserialization should be triggered by this Rest Request:

@PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE , produces = MediaType.APPLICATION_JSON_VALUE)
    public responseDto createEntity(Authentication authentication,
                                @ModelAttribute @Valid RequestDto requestDto) throws IOException {

        return service.createEntity(requestDto));
    }
}

After running this request I got a problem with the attribut "localizations":

"org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult
default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Map' for property 'localizations';
nested exception is java.lang.IllegalStateException:

It seems that Jackson is not considering my custom deserializer class MapDeserializer or any annotation is missing.

Thank you for the support

HLA
  • 41
  • 2
  • `@ModelAttribute` is for binding form variables, you want to use `@RequestBody` for (de)serializing JSON. – M. Deinum Apr 25 '22 at 12:00
  • Refer: https://stackoverflow.com/questions/70324/java-inner-class-and-static-nested-class. Use outer.inner class, RequestDto.MapDeserializer.class also fully qualify package if any. – Ironluca Apr 25 '22 at 15:36
  • I have removed the Multipart file property from the RequestDto and changed the Rest method like following (using @Requestpart):`@PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE , produces = MediaType.APPLICATION_JSON_VALUE) public dto createAward(Authentication authentication, @RequestPart RequestDto requestDto, @RequestPart MultipartFile file) throws IOException { return service.createEntity(requestDto, file)); }` It Works NOW :) – HLA Apr 27 '22 at 07:44

0 Answers0