This is the 8th day of my participation in the August More Text Challenge. For details, see:August is more challenging
Jackson practical posture summary
Using JSON for data interaction can be said to be very common, in The Java side, the common JSON parsing framework is also many, such as GSON, FastJSON and Spring MVC default Jackson; In this article, we will focus on the basic Jackson gestures, as well as the things you should know in everyday development, such as the common ones
- Normal object to JSON string
- Json string to POJO, to Map/List
- Generic support
- Hump/underline interturn, custom mapping
- Bean compliance specification
- Serialize/deserialize the exception scenario
1. Project dependency
To build a project with Maven, you need to use Jackson for serialization, and the core introduces the following packages
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
Copy the code
2. Basic posture
In Jackson, ObjectMapper is essential if you want to serialize/deserialize
Like turning an object into a Json String
public static <T> String encode(T obj) {
try {
return new ObjectMapper().writeValueAsString(obj);
} catch (Exception e) {
throw newUnsupportedOperationException(e); }}Copy the code
deserialization
public static <T> T decode(String str, Class<T> clz) {
try {
return new ObjectMapper().readValue(str, clz);
} catch (Exception e) {
throw newUnsupportedOperationException(e); }}Copy the code
Pay attention to
- One significant difference between Jackson and Gson/FastJSON is that its serialization/deserialization has declared exceptions that need to be declared or actively caught (which is not very friendly).
- Second, it is not recommended to create an ObjectMapper object every time, and reuse can be considered
3. Generic deserialization
For generic deserialization, using the above, passing in a class object, does not work very well. As with Gson/FastJson, Jackson also supports back serialization by Type
public static <T> T decode(String str, Type type) {
try {
return objectMapper.readValue(str, objectMapper.getTypeFactory().constructType(type));
} catch (Exception e) {
throw newUnsupportedOperationException(e); }}Copy the code
Focus on the above parameter, through objectMapper. GetTypeFactory () constructType JavaType objects (type) to create a need
A demo posture is as follows
GenericBean<Map> gbean2 = JacksonUtil.decode(str, new com.fasterxml.jackson.core.type
.TypeReference<GenericBean<Map>>() {}.getType());
System.out.println(gbean2);
Copy the code
4. Turn the Map/List
What’s special about turning to a normal Map/List
public static Map toMap(String str) {
try {
return objectMapper.readValue(str, Map.class);
} catch (JsonProcessingException e) {
throw newUnsupportedOperationException(e); }}public static List toList(String str) {
try {
return objectMapper.readValue(str, List.class);
} catch (JsonProcessingException e) {
throw newUnsupportedOperationException(e); }}Copy the code
5. JsonNode
JsonNode is a node object defined for Jackson, similar to Gson’s JsonObject/JsonArray and FastJson’s JsonObject/JsonArray. You can use it to manipulate JSON objects in a more user-friendly way (of course, going directly to JAVA beans is more recommended)
public static JsonNode toObj(String str) {
try {
return objectMapper.readTree(str);
} catch (JsonProcessingException e) {
throw newUnsupportedOperationException(e); }}Copy the code
Use demo as follows
String str = 12, "{\" userId \ ": \" the userName \ ": \" yh \ "and \" userMoney \ ": 12.3, \" userSkills \ ": [\" 1 \ ", \ "2 \", \ "3 \], \" extra \ ": {\" a \ ": \" 123 \ ", \ \ "b" : 345, \ \ "c" : [\ "1 \" and \ "2 \", \ "3 \], \" d \ ": 35.1}, \" hello \ ": \" hello \ "}";
JsonNode bean = JacksonUtil.toObj(str);
int userId = bean.get("userId").asInt();
Copy the code
6. Humps and underscores
Jackson conveniently supports a common case in which a JSON string key is underlined and a Java bean is named after its hump
/** * Hump down line change **@param obj
* @return* /
public static String toUnderStr(Object obj) {
ObjectMapper objectMapper = new ObjectMapper();
// The hump is underlined
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw newUnsupportedOperationException(e); }}/** * String in underline format, convert to hump format Java bean */
public static <T> T fromUnderStr(String str, Class<T> clz) {
ObjectMapper objectMapper = new ObjectMapper();
// The hump is underlined
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
try {
return objectMapper.readValue(str, clz);
} catch (JsonProcessingException e) {
throw newUnsupportedOperationException(e); }}Copy the code
As you can see from the code above, the transfer between humps and underscores is supported mainly by setting PropertyNamingStrategies, which in Jackson support the following configurations
LOWER_CAMEL_CASE
UPPER_CAMEL_CASE
SNAKE_CASE
LOWER_CASE
KEBAB_CASE
LOWER_DOT_CASE
What if I only want to do this for a single class, using the underline/hump conversion that works globally?
This can be done using the annotation @jsonnaming
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class SimpleBean implements Serializable {
private static final long serialVersionUID = -9111747337710917591L;
private Integer userId;
private String userName;
private double userMoney;
}
Copy the code
In this case, if we serialize the SimpleBean object as a JSON string, even if we call the basic new ObjectMapper().writevalueasString (SimpleBean), The output is also an underlined JSON string; Similarly, when deserializing, the underscore is turned into a hump
7. Field alias
The hump and underline names are described above, but there are other special scenarios where you can alias a field, which you can annotate with @jsonProperties
@JsonProperty("user")
private String userName;
Copy the code
When serialized as a JSON string, the key corresponding to userName is user
8. The field is ignored
When serializing, it is inevitable that some fields will not be serialized/deserialized, and there are two common ways to do so
8.1 @ JsonIgnore annotation
Simply add the @jsonignore annotation to the fields you want to ignore, such as
@Data
public class SimpleBean implements Serializable {
private static final long serialVersionUID = -9111747337710917591L;
@JsonIgnore
private SimpleBean self;
}
Copy the code
8.2 transient keyword
In addition to using the above annotations, you can also use the NATIVE JDK keyword TRANSIENT to declare fields that you want to ignore
private transient SimpleBean self;
Copy the code
Important note:
- In Jackson, the default scenario is even if the field is decorated
transient
Keywords that will not be ignored also need to be processed as follows
objectMapper = new ObjectMapper();
// Ignore the transient keyword
// case1
objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
// case2
objectMapper.setVisibility(objectMapper.getSerializationConfig()
.getDefaultVisibilityChecker()
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
Copy the code
In both of the above methods, object serialization can be achieved without the transient keyword modification
Java Bean conventions
9.1 Get /set Must be available
The Java Bean’s GET /set method must exist, otherwise the serialization and deserialization will only handle the public modified members
public class SimpleBean {
private String name;
private Long userId;
public String desc = "hello world";
public SimpleBean(a) {
name = "yhh";
userId = 10L; }}Copy the code
{“desc”:”hello world”}; Deserialization does not update name, userId;
In particular, if all members of a Java Bean object are private and there is no GET method, an exception will be thrown during serialization with the following message
No serializer found for class com.git.hui.spring.json.bean.SimpleBean and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
Copy the code
9.2 No-parameter constructors are mandatory
If a Java bean does not have a default parameterless constructor, an exception will be thrown when deserialized and cannot be instantiated
An exception message as follows
Cannot construct instance of `com.git.hui.spring.json.bean.SimpleBean` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
Copy the code
10. Json string has undefined Bean fields. Ignore Settings
By default, an exception will be thrown if there is an undefined KV in the json string, as shown in the following example
Unrecognized field "xxx" (class com.git.hui.spring.json.bean.GenericBean), not marked as ignorable
Copy the code
If you want to ignore this scenario, you need to disable the FAIL_ON_UNKNOWN_PROPERTIES configuration
new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.readValue(str, Xxx.class)
Copy the code
Expand knowledge
- For Spring MVC, the Jackson serialization framework is used by default. If we define the receiving parameter as a JSON string, will an exception be thrown if the current end passes an undefined field?
11. Ignore null when serializing output
By default, serializing a bean object to a JSON string will be output even if the member variable is null, as shown below
{
"userId" : null."userName" : null."userMoney" : 0.0."userSkills" : null."extra" : null
}
Copy the code
This case is appropriate for some scenarios. For example, when generating an interface document example, you are more concerned with the parameter description, even if it is null. But there are other scenarios where you want to ignore it, because you can save on object size
To ignore the NULL field, set it as follows
new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL)
.writerWithDefaultPrettyPrinter().writeValueAsString(xxx)
Copy the code
Key point is to configure setSerializationInclusion (JsonInclude. Include. NON_NULL)
12. The key is null
For ordinary Java beans, there is no such thing as a null key, but it can happen when you output a Map object as a JSON string, such as
Map<String, String> map = new HashMap<>();
map.put(null."123");
new ObjectMapper().writeValueAsString(map);
Copy the code
The execution above throws an exception directly
Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
Copy the code
If you want to be compatible with this scenario, you can do so as follows
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.getSerializerProvider().setNullKeySerializer(new JsonSerializer<Object>() {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeFieldName("null"); }});Copy the code
So what we’re doing here is we’re replacing a null string with a null key
instructions
- Since the key can be null, of course it can be of any other type, but when the output is serialized, it will be converted to String
Take the following case
Map map = new HashMap();
map.put(new ArrayList<>(), 123);
new ObjectMapper().writeValueAsString(map);
Copy the code
The output string is
{"[]":123}
Copy the code
13 other
The above information covers 95% of the scenarios in which Jackson is used for serialization and deserialization. As for the other relatively rare gestures, such as custom Name policy, default value type for deserialization, type conversion, json annotation support, etc., we will see if there is time to fill in later
II. The other
1. A gray Blog:liuyueyi.github.io/hexblog
A gray personal blog, record all study and work in the blog, welcome everyone to visit
2. Statement
The above content is not as good as the letter, purely the words of a family, due to the limited personal ability, there are inevitably omissions and mistakes, such as found bugs or better suggestions, welcome criticism and correction, not grudging gratitude
- Micro-blog address: small gray Blog
- QQ: A gray /3302797840
Wechat official account: a gray blog