简体   繁体   中英

Deserializing JSON-valued string

We are using Spring Boot to expose a REST endpoint which is called by a dumb client which delivers us the following:

{
    "timestamp": "2016-08-16T14:30.000Z",
    "data": "{\"amount\":1,\"product\":\"BASIC PRODUCT\"}"
}

We've created the following objects:

@JsonDeserialize(builder = Message.Builder.class)
public final class Message {
    private final String timestamp;
    private final Data data;

    public String getTimestamp() {...}
    public Data getData() {...}

    @JsonPOJOBuilder
    public static final class Builder {
        private String timestamp;
        private Data data;

        public Builder withTimestamp(final String timestamp) {...}
        public Builder withData(final Data data) {...}
    }
}

and

@JsonDeserialize(builder = Data.Builder.class)
public final class Data {
    private final String product;
    private final int amount;

    public String getProduct() {...}
    public int getAmount() {...}

    @JsonPOJOBuilder
    public static final class Builder {
        private String product;
        private int amount;

        public Builder withProduct(final String product) {...}
        public Builder withAmount(final int amount) {...}
    }
}

and exposed the endpoint as

@RequestMapping(consumes = "application/json", method = POST)
public ResponseEntity<?> receive(@RequestBody Message message) {
   /// ...
}

but control doesn't even reach the receive method and fails with 400 BAD REQUEST . I believe this has to do with the fact that data is a JSON-valued string. Does Jackson provide any annotation that I can use to force the JSON-valued string to be deserialized as an instance of Data ?

The key is in public Builder withData() method of Message.Builder.class to explicitly parse JSON-valued string to Data type. Change the method parameter to String instead of Data and call ObjectMapper().readValue(JSON-valued string, Data.class) to deserialize it into Data .

For example like this:

public Builder withData(final String jsonValue) throws JsonParseException, JsonMappingException, IOException {
    Data data = new ObjectMapper().readValue(jsonValue, Data.class);
    this.data = data;
    return this;
}

For the clarity sake here you are my whole POJOs:

Message:

public final class Message {
    private final String timestamp;
    private final Data data;

    private Message(Builder builder){
        this.timestamp = builder.timestamp;
        this.data = builder.data;
    }

    public String getTimestamp() {...}
    public Data getData() {...}

    @JsonPOJOBuilder
    public static final class Builder {
        private String timestamp;
        private Data data;

        private static ObjectMapper mapper = new ObjectMapper();

        public Builder withTimestamp(final String timestamp) {
            this.timestamp = timestamp;
            return this;
        }
        public Builder withData(final String jsonValue) throws JsonParseException, JsonMappingException, IOException {
            Data data = mapper.readValue(jsonValue, Data.class);
            this.data = data;
            return this;
        }
        public Message build() {
            return new Message(this);
        }
    } // Builder
}

Data:

public final class Data {
    private final String product;
    private final int amount;

    private Data(Builder builder){
        this.product = builder.product;
        this.amount = builder.amount;
    }

    public String getProduct() {...}
    public int getAmount() {...}

    @JsonPOJOBuilder
    public static final class Builder {
        private String product;
        private int amount;

        public Builder withProduct(final String product) {
            this.product = product;
            return this;
        }
        public Builder withAmount(final int amount) {
            this.amount = amount;
            return this;
        }
        public Data build() {
            return new Data(this);
        }
    } // Builder
}

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM