Table of contents
background
Spring
The default JSON
serialization tool uses the project address jackson
:GitHub
https://github.com/FasterXML/jackson
When we deal with front-end and back-end interface interactions, we may need to implement various personalized requirements. This article mainly introduces custom annotations, and then performs business logic processing on specific fields.
Introduction to the development environment of this article
development dependencies | Version |
---|---|
Spring Boot | 3.1.2 |
JDK | 17 |
Create a new annotation
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({
ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JsonSerialize(using = PrintFieldJsonSerializer.class)
public @interface PrintField {
Type rule() default Type.TYPE_1;
enum Type {
TYPE_1, TYPE_2
}
}
Create a new JavaBean
Use custom annotations on fields
import lombok.Builder;
import lombok.Data;
/**
* @author tangheng
*/
@Data
@Builder
public class DemoPerson {
@PrintField(rule = PrintField.Type.TYPE_1)
private String name;
@PrintField(rule = PrintField.Type.TYPE_2)
private String email;
}
Create a new JsonSerializer
for custom business logic
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
@Slf4j
@RequiredArgsConstructor
public class PrintFieldJsonSerializer extends JsonSerializer<String> {
private final PrintField.Type rule;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if(StringUtils.isBlank(value)) {
return;
}
switch (rule) {
case TYPE_1:
log.info("hello, value: {}", value);
break;
default:
log.info("rule: {}, value: {}", rule, value);
break;
}
gen.writeString(value);
}
}
Create a new AnnotationIntrospector
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.introspect.Annotated;
import java.lang.annotation.Annotation;
public class PrintFieldAnnotationIntrospector extends AnnotationIntrospector {
@Override
public Version version() {
return Version.unknownVersion();
}
@Override
public Object findSerializer(Annotated a) {
PrintField ann = _findAnnotation(a, PrintField.class);
if (ann != null) {
return new PrintFieldJsonSerializer(ann.rule());
}
return null;
}
@Override
public boolean isAnnotationBundle(Annotation ann) {
if (PrintField.class.isAssignableFrom(ann.getClass())) {
return true;
}
return false;
}
}
- This step is very critical. Use jackson's Introspector mechanism to play a link between the preceding and the following.
- Determine that there are custom annotations on the field, and then use the custom JsonSerializer
- This ties the whole thing together
unit test
class PrintFieldJsonSerializerTest extends JsonSpringbootTestBase {
private ObjectMapper objectMapper = new ObjectMapper();
@SneakyThrows
@Test
void serialize() {
objectMapper.setAnnotationIntrospector(new PrintFieldAnnotationIntrospector());
DemoPerson demoPerson = DemoPerson.builder()
.name("zhangsan")
.email("[email protected]")
.build();
String testResult = objectMapper.writeValueAsString(demoPerson);
log.info("testResult: {}", testResult);
assertTrue(StringUtils.isNotBlank(testResult));
}
}
Screenshot of unit test results
Summarize
- There are tens of millions of ways to realize a requirement. For a pursuing programmer, study the source code to find the most refined way to achieve the goal in the simplest way, which is better in terms of scalability and maintainability.
- When there is a need, don't rush to write code, study the source code, which can help us achieve our goal gracefully
- Maybe the time spent studying source code is much longer than writing code, but the harvest and sense of accomplishment are still very satisfying
- Even if the requirements are finally realized with only a few lines of code, a good programmer is never measured by the number of lines of code
- The deserialization of jackson can be realized by referring to the same principle