Starter for building web, including RESTful, applications using Spring MVC with embedded Tomcat server.
—
Jackson JSON library integration for automatic serialization and deserialization of Java objects to/from JSON in web requests and responses.
Automatic conversion between Java objects and JSON for request/response bodies.
/**
* Core Jackson ObjectMapper for JSON processing
*/
@Autowired
private ObjectMapper objectMapper;
/**
* JSON serialization to string
*/
public String writeValueAsString(Object value) throws JsonProcessingException;
/**
* JSON deserialization from string
*/
public <T> T readValue(String content, Class<T> valueType) throws JsonProcessingException;
public <T> T readValue(String content, TypeReference<T> valueTypeRef) throws JsonProcessingException;Usage Examples:
@RestController
public class DataController {
@Autowired
private ObjectMapper objectMapper;
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
// @RequestBody automatically deserializes JSON to User object
User saved = userService.save(user);
// Return value automatically serialized to JSON
return ResponseEntity.ok(saved);
}
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.findById(id);
// Automatic JSON serialization in response
return ResponseEntity.ok(user);
}
// Manual JSON processing when needed
@PostMapping("/process-json")
public ResponseEntity<String> processJson(@RequestBody String jsonString) {
try {
JsonNode jsonNode = objectMapper.readTree(jsonString);
String processedJson = objectMapper.writeValueAsString(processedNode);
return ResponseEntity.ok(processedJson);
} catch (JsonProcessingException e) {
return ResponseEntity.badRequest().body("Invalid JSON");
}
}
}Control JSON serialization/deserialization behavior using Jackson annotations.
/**
* Property naming and inclusion
*/
@JsonProperty("user_name")
private String userName;
@JsonIgnore
private String password;
@JsonInclude(JsonInclude.Include.NON_NULL)
private String optionalField;
/**
* Date/time formatting
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthDate;
/**
* Custom serializers and deserializers
*/
@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
private CustomType customField;
/**
* Polymorphic type handling
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
// Base animal properties
}Usage Examples:
public class User {
@JsonProperty("user_id")
private Long id;
@JsonProperty("full_name")
private String name;
@JsonIgnore
private String password;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<String> tags;
// getters and setters
}
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// Response JSON will use @JsonProperty names:
// {"user_id": 1, "full_name": "John Doe", "createdAt": "2023-01-01 12:00:00"}
return userService.findById(id);
}
}Configure ObjectMapper behavior programmatically.
/**
* Custom ObjectMapper configuration
*/
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
// Configure serialization
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// Configure deserialization
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
// Register modules
mapper.registerModule(new JavaTimeModule());
mapper.registerModule(new ParameterNamesModule());
// Custom property naming strategy
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
return mapper;
}
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder()
.dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
.timeZone(TimeZone.getTimeZone("UTC"))
.propertyNamingStrategy(PropertyNamingStrategies.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.featuresToEnable(SerializationFeature.INDENT_OUTPUT);
}
}HTTP message converters for JSON processing in Spring MVC.
/**
* Jackson JSON message converter
*/
public class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
public boolean canRead(Class<?> clazz, MediaType mediaType);
public boolean canWrite(Class<?> clazz, MediaType mediaType);
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage);
public void write(Object object, Type type, MediaType contentType, HttpOutputMessage outputMessage);
}
/**
* Custom message converter configuration
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
}JSON processing error handling and validation.
/**
* JSON processing exception handling
*/
@ControllerAdvice
public class JsonExceptionHandler {
@ExceptionHandler(JsonProcessingException.class)
public ResponseEntity<ErrorResponse> handleJsonProcessingException(JsonProcessingException ex) {
ErrorResponse error = new ErrorResponse("JSON_PROCESSING_ERROR", ex.getMessage());
return ResponseEntity.badRequest().body(error);
}
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ErrorResponse> handleInvalidJson(HttpMessageNotReadableException ex) {
ErrorResponse error = new ErrorResponse("INVALID_JSON", "Request body contains invalid JSON");
return ResponseEntity.badRequest().body(error);
}
@ExceptionHandler(HttpMessageNotWritableException.class)
public ResponseEntity<ErrorResponse> handleJsonWriteError(HttpMessageNotWritableException ex) {
ErrorResponse error = new ErrorResponse("JSON_WRITE_ERROR", "Failed to serialize response to JSON");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}// Core Jackson ObjectMapper
public class ObjectMapper {
public String writeValueAsString(Object value) throws JsonProcessingException;
public <T> T readValue(String content, Class<T> valueType) throws JsonProcessingException;
public <T> T readValue(String content, TypeReference<T> valueTypeRef) throws JsonProcessingException;
public JsonNode readTree(String content) throws JsonProcessingException;
public ObjectMapper configure(SerializationFeature f, boolean state);
public ObjectMapper configure(DeserializationFeature f, boolean state);
}
// Jackson builder for ObjectMapper configuration
public class Jackson2ObjectMapperBuilder {
public Jackson2ObjectMapperBuilder dateFormat(DateFormat dateFormat);
public Jackson2ObjectMapperBuilder timeZone(TimeZone timeZone);
public Jackson2ObjectMapperBuilder propertyNamingStrategy(PropertyNamingStrategy strategy);
public Jackson2ObjectMapperBuilder featuresToEnable(Object... features);
public Jackson2ObjectMapperBuilder featuresToDisable(Object... features);
public ObjectMapper build();
}
// JSON processing annotations
@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonProperty {
String value() default "";
boolean required() default false;
}
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonIgnore {
}
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface JsonInclude {
Include value() default Include.ALWAYS;
enum Include {
ALWAYS, NON_NULL, NON_ABSENT, NON_EMPTY, NON_DEFAULT, CUSTOM, USE_DEFAULTS
}
}
// Type reference for generic types
public abstract class TypeReference<T> {
protected TypeReference() {}
}
// JSON node for tree model processing
public abstract class JsonNode {
public abstract JsonNode get(String fieldName);
public abstract String asText();
public abstract int asInt();
public abstract boolean asBoolean();
public abstract boolean isArray();
public abstract boolean isObject();
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter-web