アミット・クマール:
我々は、我々が持っているシナリオ持つJSON
フィールドの2つの異なる値を持つ複数可。私たちは、それを用いたすべてのjsonsを解析したいと思いますPOJO
。以下は、これらの2つの見つけることができJSON
ペイロードを。
{
"values": [
[
{
"name": "item_name",
"value": "pool"
}
],
[
{
"name": "item_name",
"value": "Mob"
}
]
],
"name": "lines"
}
そして:
{
"values": [
{
"name": "pack",
"value": "Enter, HD"
}
],
"name": "lines"
}
私は以下のようにPOJOを指定した場合、現在、第二JSONは例外をスローします
class ValuesModel extends Serializable {
@BeanProperty
var values: List[List[ValueModel]] = _
}
私は以下のようにPOJOを指定した場合、第一JSONは例外をスローします
class ValuesModel extends Serializable {
@BeanProperty
var values: List[ValueModel] = _
}
1を作成するには、そこの方法であるPOJO
という例外をキャッチし、別のスキーマを使用して解析するよりも、一緒に両方jsonsを解析するには?私が使用していJackson
解析します。
マイケルZiober:
このようなケースでは、複数の処理したい場所JSON
のスキーマを同じにそれをデシリアライズすることができPOJO
、カスタムデシリアライザを実装し、必要なすべてのシナリオを実装する必要がモデル。
以下は、例を見つけることができますJava
両方のdeserialiseする方法JSON
ペイロードを:
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;
}
}
カスタムデシリアライザを登録するには、使用することができ@JsonDeserialize
、注釈を。
@JsonDeserialize(using = ValuesModelJsonDeserializer.class)
private List<ValueModel> values;