Advanced JSON Techniques
Custom Serialization and Deserialization
Creating Custom Serializers
public class CustomDateSerializer extends JsonSerializer<Date> {
private static final SimpleDateFormat dateFormat
= new SimpleDateFormat("yyyy-MM-dd");
@Override
public void serialize(Date date, JsonGenerator generator,
SerializerProvider provider) throws IOException {
String formattedDate = dateFormat.format(date);
generator.writeString(formattedDate);
}
}
Custom Deserializer Example
public class CustomDateDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat
= new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException {
String dateString = parser.getText();
try {
return dateFormat.parse(dateString);
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid date format");
}
}
}
JSON Annotations
Common Jackson Annotations
Annotation |
Purpose |
@JsonProperty |
Customize property names |
@JsonIgnore |
Exclude fields from serialization |
@JsonFormat |
Format date/number fields |
@JsonSerialize |
Use custom serializer |
@JsonDeserialize |
Use custom deserializer |
Advanced Mapping Techniques
Polymorphic Deserialization
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = Employee.class, name = "employee"),
@JsonSubTypes.Type(value = Manager.class, name = "manager")
})
public abstract class Person {
private String name;
// Common properties
}
JSON Streaming Processing
graph TD
A[JSON Input Stream] --> B[JsonParser]
B --> C{Parse Events}
C --> |START_OBJECT| D[Process Object]
C --> |END_OBJECT| E[Complete Processing]
C --> |KEY_NAME| F[Handle Key]
C --> |VALUE| G[Process Value]
Streaming Parser Example
public void processLargeJsonFile(InputStream inputStream) throws Exception {
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(inputStream);
while (parser.nextToken() != null) {
String fieldName = parser.getCurrentName();
JsonToken token = parser.getCurrentToken();
switch (token) {
case START_OBJECT:
// Begin object processing
break;
case FIELD_NAME:
// Handle specific fields
break;
case VALUE_STRING:
// Process string values
break;
}
}
}
JSON Path Querying
public class JsonPathExample {
public void extractData(String jsonContent) {
DocumentContext context = JsonPath.parse(jsonContent);
// Extract specific values
List<String> names = context.read("$.users[*].name");
// Complex filtering
List<String> filteredUsers = context.read(
"$.users[?(@.age > 25)].name"
);
}
}
Comparison of Parsing Strategies
Strategy |
Use Case |
Performance |
Memory Usage |
Object Mapping |
Small to Medium JSON |
Moderate |
High |
Streaming |
Large Files |
Low |
Low |
JSON Path |
Selective Extraction |
High |
Moderate |
Error Handling Strategies
public class RobustJsonParsing {
public Optional<User> parseUserSafely(String jsonContent) {
try {
ObjectMapper mapper = new ObjectMapper();
return Optional.of(
mapper.readValue(jsonContent, User.class)
);
} catch (JsonProcessingException e) {
// Log error, return empty optional
return Optional.empty();
}
}
}
Best Practices
- Use appropriate parsing technique based on data size
- Implement robust error handling
- Consider memory and performance constraints
- Validate JSON before complex processing
By mastering these advanced JSON techniques in LabEx Java projects, developers can handle complex data processing scenarios with confidence and efficiency.