Reputation: 29477
Please note: There are many questions on this site about how to use custom Jackson deserializers...this question is not one more of those! This questions has to do with using a deserializer under very unique circumstances (none of which have previous questions/answers on this site!).
Spring Boot using Jackson for JSON serialization here. I have two POJOs that are used in the @RequestBody
(HTTP request entity) for a POST endpoint:
@JsonDeserialize(using = FizzDeserializer.class)
public class Fizz {
private String name;
private String label;
private Integer code;
// Getters, setters & ctors
}
@JsonDeserialize(using = BuzzDeserializer.class)
public class Buzz {
private String id;
private String locale;
private Set<Fizz> fizzes;
// Getters, setters & ctors
}
@RestController
@RequestMapping("v1/data/buzzes")
public class BuzzController {
@PostMapping
public void updateBuzz(@RequestBody Buzz buzz) {
// do whatever
}
}
I want HTTP clients to be able to POST the following JSON to this endpoint:
{
"id" : "12345-67890",
"locale" : "en_US",
"fizzes" : [
"foo",
"bar"
]
}
...where "foo"
and "bar
" are the Fizz#names
of two different Fizz
instances. In other words, I don't want the client to have to specify the entire Fizz
object, just specify its name
as a JSON string (my app + DB guarantee Fizzes have unique names).
So I'm using a custom JsonDeserializer
to accomplish all this mapping:
public BuzzDeserializer extends JsonDeserializer<Buzz> {
Buzz deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode buzzNode = jsonParser.readValueAsTree();
String id = buzzNode.get("id");
String locale = buzzNode.get("locale");
// TODO: How to read "foo" and "bar" (etc.) into a Set<Fizz> instances?
Set<Fizz> fizzes = ???
new Buzz(id, locale, fizzes);
}
}
public FizzDeserializer extends JsonDeserializer<Fizz> {
private FizzDAO fizzDAO;
// Getters, setters & ctors...
Fizz deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode fizzNode = jsonParser.readValueAsTree();
// If I can get access to "foo"/"bar"/etc. string somehow, I can look up the Fizz using the DAO:
String fooBarEtcStr = ???
return fizzDAO.findFizzByName(fooBarEtcStr);
}
However I'm not sure how I can read the JSON fizzes
array into a Set<Fizz>
inside this deserializer. Any ideas?
Upvotes: 0
Views: 165
Reputation: 3364
Taken from the comments to the question, the only problem seems to be to get the JSON array. Provided that the service or DAO to lookup is already injected or provided in the serializer, try something along the lines:
final JsonNode arr = buzzNode.get("fizzes");
if (arr.isArray()) {
final Set<Fizz> fizzes = Sets.newHashSetWithExpectedSize(arr.size());
for (JsonNode obj : arr) {
final String name = obj.asText();
Fizz fizz = // load from DAO
fizzes.add(fizz);
}
}
This can of course be optimised by collecting the String
values and use only one DAO
call. Also some java8 streaming could make the code less verbose.
Upvotes: 1