Jackson JSON反序列化:将子节点列表转换为POJO列表
Solution for Deserializing in Custom Deserializer
subnode into ListGot it, let's break down how to implement this properly. Since you're already extending StdDeserializer<MyObject>, you can use Jackson's built-in tools to convert the subnode array into a list of your Subnode POJOs cleanly.
Step-by-Step Implementation
Here's a complete example of your custom deserializer, along with the supporting POJOs:
First, your Subnode and MyObject classes (assuming they have standard getters/setters or use Jackson's annotations for field access):
public class Subnode { private String snProperty1; private String snProperty2; // ... add other properties as needed // Default constructor required for Jackson deserialization public Subnode() {} // Add getters and setters for all properties public String getSnProperty1() { return snProperty1; } public void setSnProperty1(String snProperty1) { this.snProperty1 = snProperty1; } public String getSnProperty2() { return snProperty2; } public void setSnProperty2(String snProperty2) { this.snProperty2 = snProperty2; } } public class MyObject { private String property1; private List<Subnode> subnodeList; // ... add other top-level properties as needed public MyObject() {} // Getters and setters public String getProperty1() { return property1; } public void setProperty1(String property1) { this.property1 = property1; } public List<Subnode> getSubnodeList() { return subnodeList; } public void setSubnodeList(List<Subnode> subnodeList) { this.subnodeList = subnodeList; } }
Now the custom deserializer implementation:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.databind.type.CollectionType; import java.io.IOException; import java.util.List; public class MyObjectDeserializer extends StdDeserializer<MyObject> { // Default constructor required for Jackson public MyObjectDeserializer() { this(null); } public MyObjectDeserializer(Class<?> vc) { super(vc); } @Override public MyObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 1. Read the entire JSON structure into a JsonNode for navigation JsonNode rootNode = p.getCodec().readTree(p); // 2. Initialize your target MyObject instance MyObject myObject = new MyObject(); // 3. Handle top-level properties like property1 if (rootNode.has("property1")) { myObject.setProperty1(rootNode.get("property1").asText()); } // 4. Convert the subnode array to List<Subnode> if (rootNode.has("subnode")) { JsonNode subnodeArray = rootNode.get("subnode"); if (subnodeArray.isArray()) { // Create a typed reference for List<Subnode> so Jackson knows the generic type CollectionType listType = ctxt.getTypeFactory() .constructCollectionType(List.class, Subnode.class); // Use the deserialization context to parse the array into the list List<Subnode> subnodeList = ctxt.readValue(subnodeArray.traverse(p.getCodec()), listType); myObject.setSubnodeList(subnodeList); } else { // Optional: Handle non-array cases (return empty list or throw error) throw new IOException("Expected 'subnode' to be a JSON array"); } } else { // Optional: Handle missing subnode (e.g., set empty list instead of throwing) myObject.setSubnodeList(List.of()); } // 5. Add handling for other top-level properties here // ... return myObject; } }
Key Details Explained
- Reading the JSON Tree:
p.getCodec().readTree(p)gives you a navigableJsonNoderepresenting the entire input JSON, making it easy to access nested nodes likesubnode. - Generic Type Handling: Using
ctxt.getTypeFactory().constructCollectionType(...)tells Jackson exactly what type of list we want to deserialize into (critical for generic types likeList<Subnode>). - Reusing Configurations:
subnodeArray.traverse(p.getCodec())ensures we use the sameObjectMapperinstance from the current deserialization context, preserving any custom configurations (like date formats or other deserializers) you've set up. - Flexible Error Handling: The checks for
subnodeexistence and array type let you handle edge cases gracefully—you can adjust this to return an empty list instead of throwing an exception if that fits your use case better.
Registering the Deserializer
To make Jackson use your custom deserializer, you have two options:
- Annotation-based: Add
@JsonDeserializeto yourMyObjectclass:
@JsonDeserialize(using = MyObjectDeserializer.class) public class MyObject { // ... existing code }
- ObjectMapper configuration: Register the deserializer directly on your
ObjectMapper:
ObjectMapper mapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(MyObject.class, new MyObjectDeserializer()); mapper.registerModule(module);
内容的提问来源于stack exchange,提问作者geco17
相关产品推荐
相关产品推荐

