Jackson自定义转换器

本文详细介绍如何使用Jackson库中的@JsonDeserialize注解进行JSON到JavaBean的转换,包括自定义转换器、日期类型的处理及注解的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用jackson进行json和java bean转换时,可以使用注解自定义转换器进行转换。

 

@JsonDeserialize注解源码
方法注释中写了,using 方法是作用在method上的。

 

package com.fasterxml.jackson.databind.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.KeyDeserializer;
import com.fasterxml.jackson.databind.util.Converter;

/**
 * Annotation use for configuring deserialization aspects, by attaching
 * to "setter" methods or fields, or to value classes.
 * When annotating value classes, configuration is used for instances
 * of the value class but can be overridden by more specific annotations
 * (ones that attach to methods or fields).
 *<p>
 * An example annotation would be:
 *<pre>
 *  &#64;JsonDeserialize(using=MySerializer.class,
 *    as=MyHashMap.class,
 *    keyAs=MyHashKey.class,
 *    contentAs=MyHashValue.class
 *  )
 *</pre>
 *<p>
 * Something to note on usage:
 *<ul>
 * <li>All other annotations regarding behavior during building should be on <b>Builder</b>
 *    class and NOT on target POJO class: for example &#64;JsonIgnoreProperties should be on
 *    Builder to prevent "unknown property" errors.
 *  </li>
 * <li>Similarly configuration overrides (see {@link com.fasterxml.jackson.databind.ObjectMapper#configOverride})
 *    should be targeted at Builder class, not target POJO class.
 *  </li>
 * </ul>
 *
 */
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@com.fasterxml.jackson.annotation.JacksonAnnotation
public @interface JsonDeserialize
{
    // // // Annotations for explicitly specifying deserialize/builder

    /**
     * Deserializer class to use for deserializing associated value.
     * Depending on what is annotated,
     * value is either an instance of annotated class (used globablly
     * anywhere where class deserializer is needed); or only used for
     * deserializing property access via a setter method.
     */
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends JsonDeserializer> using()
        default JsonDeserializer.None.class;

    /**
     * Deserializer class to use for deserializing contents (elements
     * of a Collection/array, values of Maps) of annotated property.
     * Can only be used on instances (methods, fields, constructors),
     * and not value classes themselves.
     */
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends JsonDeserializer> contentUsing()
        default JsonDeserializer.None.class;

    /**
     * Deserializer class to use for deserializing Map keys
     * of annotated property.
     * Can only be used on instances (methods, fields, constructors),
     * and not value classes themselves.
     */
    public Class<? extends KeyDeserializer> keyUsing()
        default KeyDeserializer.None.class;

    /**
     * Annotation for specifying if an external Builder class is to
     * be used for building up deserialized instances of annotated
     * class. If so, an instance of referenced class is first constructed
     * (possibly using a Creator method; or if none defined, using default
     * constructor), and its "with-methods" are used for populating fields;
     * and finally "build-method" is invoked to complete deserialization.
     */
    public Class<?> builder() default Void.class;

    // // // Annotations for specifying intermediate Converters (2.2+)
    
    /**
     * Which helper object (if any) is to be used to convert from Jackson-bound
     * intermediate type (source type of converter) into actual property type
     * (which must be same as result type of converter). This is often used
     * for two-step deserialization; Jackson binds data into suitable intermediate
     * type (like Tree representation), and converter then builds actual property
     * type.
     *
     * @since 2.2
     */
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends Converter> converter() default Converter.None.class;

    /**
     * Similar to {@link #converter}, but used for values of structures types
     * (List, arrays, Maps).
     *
     * @since 2.2
     */
    @SuppressWarnings("rawtypes") // to work around JDK8 bug wrt Class-valued annotation properties
    public Class<? extends Converter> contentConverter() default Converter.None.class;
    
    
    // // // Annotations for explicitly specifying deserialization type
    // // // (which is used for choosing deserializer, if not explicitly
    // // // specified

    /**
     * Concrete type to deserialize values as, instead of type otherwise
     * declared. Must be a subtype of declared type; otherwise an
     * exception may be thrown by deserializer.
     *<p>
     * Bogus type {@link Void} can be used to indicate that declared
     * type is used as is (i.e. this annotation property has no setting);
     * this since annotation properties are not allowed to have null value.
     *<p>
     * Note: if {@link #using} is also used it has precedence
     * (since it directly specified
     * deserializer, whereas this would only be used to locate the
     * deserializer)
     * and value of this annotation property is ignored.
     */
    public Class<?> as() default Void.class;

    /**
     * Concrete type to deserialize keys of {@link java.util.Map} as,
     * instead of type otherwise declared.
     * Must be a subtype of declared type; otherwise an exception may be
     * thrown by deserializer.
     */
    public Class<?> keyAs() default Void.class;

    /**
     * Concrete type to deserialize content (elements
     * of a Collection/array, values of Maps) values as,
     * instead of type otherwise declared.
     * Must be a subtype of declared type; otherwise an exception may be
     * thrown by deserializer.
     */
    public Class<?> contentAs() default Void.class;
}
 

 

 

1.以日期类型为例

@JsonDeserialize(using= DateJsonDeserializer.class) // Json ==> Bean,需要写到Setter方法上
public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}

@JsonSerialize(using= DateJsonSerializer.class) // Bean ==> Json,需要写到Getter方法上
public Date getCreateTime() {
    return createTime;
}

 

自定义转换方法: 

public class DateJsonDeserializer extends JsonDeserializer<Date> {
	public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	@Override
	public Date deserialize(com.fasterxml.jackson.core.JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, com.fasterxml.jackson.core.JsonProcessingException {
 
		try {
			if(jsonParser!=null&&StringUtils.isNotEmpty(jsonParser.getText())){
				return format.parse(jsonParser.getText());
			}else {
				return null;
			}
 
		} catch(Exception e) {
			System.out.println(e.getMessage());
			throw new RuntimeException(e);
		}
	}

}

 

public class DateJsonSerializer extends JsonSerializer<Date> {
	public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
	@Override
	public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
		jsonGenerator.writeString(format.format(date));
	}

}

 

### Jackson 自定义序列化与反序列化的实现 为了实现在 Spring Boot 应用程序中的自定义序列化和反序列化,可以利用 `Jackson` 提供的相关功能来处理复杂的数据转换需求。 #### 定义自定义的序列化器 当需要控制对象到 JSON 的转换过程时,可以通过创建一个类并继承 `JsonSerializer<T>` 来完成特定类型的序列化逻辑。例如: ```java public class CustomDateSerializer extends JsonSerializer<Date> { @Override public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); String formattedDate = formatter.format(value); gen.writeString(formattedDate); } } ``` 此代码片段展示了如何通过重写 `serialize()` 方法来自定义日期格式[^1]。 #### 注册自定义序列化器 为了让 Jackson 使用上述定制好的序列化器,在实体类字段上应用相应的注解即可: ```java @JsonSerialize(using = CustomDateSerializer.class) private Date creationDate; ``` 这使得每当该属性被序列化成 JSON 字符串时都会调用指定的方法来进行特殊处理。 #### 创建自定义反序列化器 对于从 JSON 到 Java 对象的过程,则需编写一个实现了 `JsonDeserializer<T>` 接口的新类用于解析输入流数据,并将其映射为目标类型实例。下面是一个简单的例子说明怎样构建这样的组件: ```java public class DecimalFormatJsonDeserializer extends JsonDeserializer<BigDecimal> { private final NumberFormat format; public DecimalFormatJsonDeserializer() { this.decimalFormat = NumberFormat.getInstance(); } @Override public BigDecimal deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { try { return new BigDecimal(format.parse(p.getValueAsString()).doubleValue()); } catch (ParseException e) { throw new RuntimeException(e.getMessage(), e); } } } ``` 这里的关键在于覆盖默认行为以适应应用程序的具体要求[^2]。 #### 配置反序列化器 要使自定义的反序列化器生效,除了标记目标字段外,还需确保使用了正确的组合注解以便让框架识别这些扩展点: ```java @JsonIgnoreProperties(ignoreUnknown = true) class MyClass { @JsonDeserialize(using=DecimalFormatJsonDeserializer.class) private BigDecimal amount; } ``` 值得注意的是,如果希望此类配置能够应用于整个项目范围内而不仅仅是单个成员变量级别,那么可以在全局层面注册它们作为模块的一部分或者直接修改 ObjectMapper 实例设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值