Springboot自定义出入参格式序列化
          目录
          
        
        
      springboot自定义出入参格式序列化
场景:由于某种特殊原因,java侧需要对输入的double类型的经纬度转为D-M-S的格式,在对象出参的时候又需要将D-M-S转为小数类型。
DMS转换工具类
public class DmsToDecimalConverter {
    // 正则表达式用于解析DMS格式的字符串
    private static final String REGEX_DMS = "([0-9]+)°([0-9]+)′([0-9.]+)″";
    /**
     * Validates whether the given string is in correct DMS format for latitude or longitude.
     *
     * @param dmsString The string to validate.
     * @return true if the string matches the DMS format, false otherwise.
     */
    public static boolean isValidDms(String dmsString) {
        Pattern pattern = Pattern.compile(REGEX_DMS);
        Matcher matcher = pattern.matcher(dmsString.trim());
        return matcher.matches();
    }
    /**
     * 将DMS格式的经纬度转换为十进制度(DD)。
     * 
     * @param dms DMS格式的经纬度字符串,例如:"120°18′20″"
     * @return 十进制度(DD)的值
     */
    public static double dmsToDecimal(String dms) {
        if (dms == null || dms.isEmpty()) {
            throw new IllegalArgumentException("DMS string cannot be null or empty.");
        }
        String[] parts = dms.split("°|′|″");
        if (parts.length != 3) {
            throw new IllegalArgumentException("Invalid DMS format: " + dms);
        }
        double degrees = Double.parseDouble(parts[0]);
        double minutes = Double.parseDouble(parts[1]);
        double seconds = Double.parseDouble(parts[2]);
        return degrees + minutes / 60 + seconds / 3600;
    }
    /**
     * 将十进制度(DD)的经纬度转换为DMS格式的字符串。
     * 
     * @param decimal 十进制度(DD)的值
     * @return DMS格式的经纬度字符串
     */
    public static String decimalToDms(double decimal) {
        long deg = (long) decimal;
        double minSec = (decimal - deg) * 60;
        long min = (long) minSec;
        double sec = (minSec - min) * 60;
        DecimalFormat df = new DecimalFormat("#.00");
        return deg + "°" + min + "′" + (int) sec + "″";
    }
}入参转换
创建自定义反序列化类
创建一个自定义反序列化类:LongitudeAndLatitudeDoubleToStringSerialize继承com.fasterxml.jackson.databind.JsonDeserializer
/**
 * @author wuhming
 * @description ""
 * @date 2024/7/31 09:55
 */
public class LongitudeAndLatitudeDoubleToStringSerialize extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        JsonToken jsonToken = jsonParser.currentToken();
        if(jsonToken == JsonToken.VALUE_STRING){
            String value = jsonParser.getValueAsString();
            if(value != null && !DmsToDecimalConverter.isValidDms(value)){
                String decimalToDms = DmsToDecimalConverter.decimalToDms(Double.parseDouble(value.trim()));
                return decimalToDms;
            }
        }
        return jsonParser.getText();
    }
}com.fasterxml.jackson.core.JsonParser基础方法
- 读取基本类型:
- getText()读取字符串值。
- getBooleanValue()读取布尔值。
- getIntValue()读取整数值。
- getLongValue()读取长整型值。
- getDoubleValue()读取浮点数值。
 
- 读取数组:
- nextToken()移动到下一个token,并检查token类型。
- nextValue()读取下一个值。
 
- 读取对象:
- nextToken()和- nextValue()也可以用于读取对象的键值对。
 
- 判断当前token类型:
- currentToken()返回当前token的类型。
- hasNext()判断是否有下一个元素。
 
使用
在入参实体类字段上面使用:
@Data
public class TrackInfo implements Serializable {
    @ApiModelProperty(value = "序列id", hidden = true)
    private Long sequenceId;
    @ApiModelProperty("经度")
    @JsonDeserialize(using = LongitudeAndLatitudeDoubleToStringSerialize.class)
    private String longitude;
    @ApiModelProperty("纬度")
    @JsonDeserialize(using = LongitudeAndLatitudeDoubleToStringSerialize.class)
    private String latitude;
    @ApiModelProperty("时间点")
    private String datePoint;
    @ApiModelProperty("速度")
    private String speed;
    @ApiModelProperty("航向")
    private String heading;
    @ApiModelProperty("高度")
    private String height;
}出参转换
创建自定义序列化类
创建一个自定义序列化类:LongitudeAndLatitudeToDoubleStringSerialize继承com.fasterxml.jackson.databind.JsonSerializer
/**
 * @author wuhming
 * @description ""
 * @date 2024/7/30 16:13
 */
public class LongitudeAndLatitudeToDoubleStringSerialize extends JsonSerializer<String> {
    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if(value != null && DmsToDecimalConverter.isValidDms(value)){
            double dmsToDecimal = DmsToDecimalConverter.dmsToDecimal(value);
            jsonGenerator.writeString(String.valueOf(dmsToDecimal));
        }
    }
}使用
在出参实体类字段上面使用:
@Data
@AllArgsConstructor
@NoArgsConstructor
public  class Point {
    @ApiModelProperty("经度")
    @JsonSerialize(using = LongitudeAndLatitudeToDoubleStringSerialize.class)
    private String longitude;
    @ApiModelProperty("纬度")
    @JsonSerialize(using = LongitudeAndLatitudeToDoubleStringSerialize.class)
    private String latitude;
    @ApiModelProperty("时间点")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date datePoint;
}