Nós temos um cenário onde temos JSON
s com 2 valores diferentes para um campo. Nós gostaríamos de analisar todos os jsons usando o mesmo POJO
. Abaixo, você pode encontrar estes 2 JSON
cargas úteis:
{
"values": [
[
{
"name": "item_name",
"value": "pool"
}
],
[
{
"name": "item_name",
"value": "Mob"
}
]
],
"name": "lines"
}
E:
{
"values": [
{
"name": "pack",
"value": "Enter, HD"
}
],
"name": "lines"
}
Atualmente, se eu especificar POJO como abaixo, segundo json lança exceção
class ValuesModel extends Serializable {
@BeanProperty
var values: List[List[ValueModel]] = _
}
se eu especificar POJO como abaixo, 1º json lança exceção
class ValuesModel extends Serializable {
@BeanProperty
var values: List[ValueModel] = _
}
Existe uma maneira de criar um POJO
para analisar ambos os jsons juntos em vez de pegar exceção e analisar com outro esquema? Eu estou usando Jackson
para analisar.
Em casos como este onde você quer lidar com mais do que um JSON
esquema e ser capaz de desserializar-lo para o mesmo POJO
modelo que você precisa para implementar deserialiser personalizado e implementar todos os cenários necessários.
Abaixo, você pode encontrar exemplo em Java
como deserialise ambas as JSON
cargas úteis:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.node.MissingNode;
import com.fasterxml.jackson.databind.type.SimpleType;
import com.fasterxml.jackson.databind.util.TokenBuffer;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./src/main/resources/test.json");
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(jsonFile, ValuesModel.class));
}
}
class ValuesModelJsonDeserializer extends JsonDeserializer<List<ValueModel>> {
@Override
public List<ValueModel> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
final JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(SimpleType.constructUnsafe(ValueModel.class));
final JsonNode root = p.readValueAsTree();
// If node is a JSON object
if (root.isObject()) {
return Collections.singletonList(deserialize(p.getCodec(), root, deserializer, ctxt));
}
if (!root.isArray()) {
// value is null or primitive
return Collections.emptyList();
}
return StreamSupport.stream(root.spliterator(), false)
.map(this::unwrap)
.filter(node -> !node.isMissingNode())
.map(node -> deserialize(p.getCodec(), node, deserializer, ctxt))
.collect(Collectors.toList());
}
private JsonNode unwrap(JsonNode node) {
if (node.isArray()) {
if (node.isEmpty()) {
return MissingNode.getInstance();
}
return node.iterator().next();
}
return node;
}
private ValueModel deserialize(ObjectCodec codec, JsonNode value, JsonDeserializer<Object> valueDeser, DeserializationContext ctxt) {
try (JsonParser jsonParser = createNestedParser(codec, value)) {
return (ValueModel) valueDeser.deserialize(jsonParser, ctxt);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
private JsonParser createNestedParser(ObjectCodec codec, JsonNode value) throws IOException {
TokenBuffer buffer = new TokenBuffer(codec, false);
codec.writeTree(buffer, value);
JsonParser parser = buffer.asParser();
parser.nextToken();
return parser;
}
}
Para registrar costume deserialiser você pode usar @JsonDeserialize
a anotação:
@JsonDeserialize(using = ValuesModelJsonDeserializer.class)
private List<ValueModel> values;