当前位置 : 首页 » 文章分类 :  开发  »  Jackson

Jackson

Jackson 使用笔记

FasterXML / jackson
https://github.com/FasterXML/jackson


变量命名方式

Lower Camel Case 小驼峰式

如果第一个单词首字母小写,称之为 Lower Camel Case 小驼峰式,例如 “getUserName”。

Upper Camel Case 大驼峰/Pascal

如果第一个单词首字母大写,称之为 Upper Camel Case 大驼峰式,或者 Pascal 命名法(Pascal Case),例如 “GetUserName”。

Snake Case 蛇式(下划线分割)

如果所有单词都小写,称之为 lower snake case(小蛇式),例如”get_user_name”。
如果所有单词都大写,称之为 upper snake case(大蛇式),例如”GET_USER_NAME”。

Kebab Case 烤肉式(中线分割)

名称中间的标点被替换成连字符(-),所有单词都小写,例如”get-user-name”。


Jackson 版本和依赖包

Jackson 1.x 的包名带有 codehaus 关键字,maven 依赖的 groupid 是 org.codehaus.jackson
Jackson 2.x 的包名带有 fasterxml 关键字,maven 依赖的 groupid 是 com.fasterxml.jackson.core

Jackson 2.x(fasterxml)主要依赖包

Jackson 2.x(fasterxml) 主要包含三个依赖

  • jackson-core 核心包
  • jackson-annotations 注解包
  • jackson-databind 数据绑定包

依赖关系为,jackson-databind 依赖 jackson-core 和 jackson-annotations
所以只需要在项目中引入 databind,其他两个就会自动引入

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.1.0</version>
</dependency>

Jackson 1.x(codehaus)主要依赖包

Jackson 1.x(codehaus) 主要包含两个依赖

  • jackson-core-asl
  • jackson-mapper-asl

其中 jackson-mapper-asl 依赖 jackson-core-asl
所以只需要引入 jackson-mapper-asl 的依赖就可以了

<dependency>
  <groupId>org.codehaus.jackson</groupId>
  <artifactId>jackson-mapper-asl</artifactId>
  <version>1.9.11</version>
</dependency>

ObjectMapper 配置

关闭 FAIL_ON_EMPTY_BEANS

jackson 序列化 bean 时,遇到 null 默认会报错,关闭此属性即可。
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

关闭 FAIL_ON_UNKNOWN_PROPERTIES

JSON 字符串中含有我们并不需要的字段,那么当对应的实体类中不含有该字段时,会抛出一个异常,此设置不抛异常
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
等于
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

JsonInclude.Include.NON_NULL

设置 Jackson 序列化时只包含不为空的字段
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

INDENT_OUTPUT缩进美化输出

objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);


Jackson枚举反序列化大小写无关

默认只有和枚举名完全相同(包括大小写)的才能自动反序列化。

例如枚举定义的是 TYPE 传入小写的 type 是无法自动反序列化的,会报错:
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.masikkk.enums.TypeEnum from String “alert”: not one of the values accepted for Enum class: [ALERT, COMMENT]
at [Source: (PushbackInputStream); line: 5, column: 14] (through reference chain: com.masikkk.vo.MessageVO[“type”])

有下面几种方法:
方法一、@JsonProperty 旁边搭配 @JsonAlias({"location", "LOCATION", "Location"}) 注解,忽略大小写。

方法二、使用自定义的 JsonDeserializer 反序列化器

方法三、使用 @JsonFormat(with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES) 设置单字段忽略大小写。

方法四、配置全局 ObjectMapper 属性的 ACCEPT_CASE_INSENSITIVE_PROPERTIES 为 true

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

方法五、如果使用的是 SpringBoot 2.1.x 及以上,可直接在 application.yml 中配置 Spring Jackson 属性
spring.jackson.mapper.ACCEPT_CASE_INSENSITIVE_ENUMS = true

spring.jackson.mapper.accept-case-insensitive-enums = true
或 yml

spring:
  jackson:
    mapper:
      accept-case-insensitive-enums: true

ObjectMapper 常用方法

writeValueAsString() 序列化

public String writeValueAsString(Object value) throws JsonProcessingException

将给定的 Java 类序列化为 json 串。


readValue() 反序列化

public <T> T readValue(String content, Class<T> valueType) throws JsonProcessingException, JsonMappingException
public <T> T readValue(String content, TypeReference<T> valueTypeRef) throws JsonProcessingException, JsonMappingException
public <T> T readValue(String content, JavaType valueType) throws JsonProcessingException, JsonMappingException

将给定的 json 串反序列化为指定类型

Json串转Java Map对象

import org.codehaus.jackson.map.ObjectMapper;

ObjectMapper mapper = new ObjectMapper();
String jsonStr = "{\"key2\":\"value1\",\"key2\":\"value2\"}";
Map<String, Object> tmpMap = mapper.readValue(jsonStr, Map.class);

convertValue() 类型转换

public <T> T convertValue(Object fromValue, Class<T> toValueType) throws IllegalArgumentException
public <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) throws IllegalArgumentException
public <T> T convertValue(Object fromValue, JavaType toValueType) throws IllegalArgumentException

类型转换便捷方法,此方法相当于先将 fromValue 序列化为 json 串,然后再反序列化为 toValueType 类型,只不过内部用临时缓冲区实现转换。

Java Object和Map互转

1、object 转 Map

ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.convertValue(new Object(), Map.class);

2、 Map 转 Object

ObjectMapper objectMapper = new ObjectMapper();
User user = objectMapper.convertValue(new HashMap<>(), User.class);

writerWithDefaultPrettyPrinter() 漂亮打印

public ObjectWriter writerWithDefaultPrettyPrinter()

构造一个使用默认漂亮打印格式的 ObjectWriter, 常用于格式化日志打印。

log.info(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object));

copy() 拷贝实例

public ObjectMapper copy() {
    _checkInvalidCopy(ObjectMapper.class);
    return new ObjectMapper(this);
}

拷贝当前 ObjectMapper 实例,常用于创建多个不同配置属性的 ObjectMapper 实例。


TypeReference 泛型反序列化

fastjson 和 Jackson 都提供了用于处理泛型反序列化的类 TypeReference, 用于将json串直接反序列化为具体类型,如果不使用 TypeReference 会反序列化为一堆map

例如

// 定义一个通用的 包裹单个bean的 http响应结构,具体的bean类型是泛型
public class CommonBeanResponse<T> {
    private T data;

    @JsonProperty("request_id")
    private String requestId;

    @JsonProperty("server_time")
    private long serverTime;

    @JsonProperty("result_code")
    private String resultCode;

    private String message;

    public T getData() { return data; }
    public void setData(T data) { this.data = data; }
    // 其他 getter  setter 省略
    ...

    public static void main(String[] args) {
      CommonBeanResponse<UserBean> responseSrc = new CommonBeanResponse<>();
      responseSrc.setData(new UserBean());
      String jsonStr = objectMapper.writeValueAsString(responseSrc);

      // 正确,可反序列化为具体的 UserBean
      CommonBeanResponse<UserBean> responseDst = objectMapper.readValue(jsonStr, new TypeReference<CommonBeanResponse<UserBean>>() {});

      // 错误,反序列化后 data域是一堆 k-v map
      CommonBeanResponse<UserBean> responseDst2 = objectMapper.readValue(jsonStr, CommonBeanResponse.class);
    }
}

再比如直接读取到 List

List<UserBean> userBeans = getUserBeanList();
String jsonStr = objectMapper.writeValueAsString(userBeans);
List beanList  = objectMapper.readValue(jsonStr, new TypeReference<List<UserBean>>() {});

为什么使用TypeReference (解释原理)
https://yq.aliyun.com/articles/609441

TypeReference – 让Jackson Json在List/Map中识别自己的Object
https://blog.csdn.net/ssjiang/article/details/7769525

alibaba/fastjson - TypeReference
https://github.com/alibaba/fastjson/wiki/TypeReference


Jackson 常用注解

@JsonProperty 字段与成员变量映射

用于属性,把属性的名称序列化时转换为另外一个名称。示例:
@JsonProperty(“birth_date”)
private Date birthDate;

@JsonProperty可以指定字段的命名(还可以指定这个字段需要参与序列化和反序列化)。
@JsonProperty.value:指定的字段名字
@JsonProperty.index:指定顺序,默写数据格式是基于顺序(JSON不是这种数据格式)
@JsonProperty.defaultValue:默认值。注意:这个属性目前为止并没有被core和data-bind使用;制备一些扩展模块使用。

Jackson 框架的高阶应用
https://www.ibm.com/developerworks/cn/java/jackson-advanced-application/index.html


@JsonNaming 序列化命名策略

@JsonNaming 注解用来指定属性序列化使用的命名策略,覆盖默认实现。可以通过 value 属性指定策略,包括自定义策略。

除了默认的 LOWER_CAMEL_CASE 机制外,Jackson 还提供了四种内置命名策略:
KebabCaseStrategy “Lisp” 风格,采用小写字母、连字符作为分隔符,例如 “lower-case” 或 “first-name”
LowerCaseStrategy 所有的字母小写,没有分隔符,例如 lowercase
SnakeCaseStrategy 所有的字母小写,下划线作为名字之间分隔符,例如 snake_case.
UpperCamelCaseStrategy 所有名字(包括第一个字符)都以大写字母开头,后跟小写字母,没有分隔符,例如 UpperCamelCase

例如常用的 驼峰 转 下划线分隔
单个类的注解命名

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class MyClass {

}

全局命名
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)

注意:
1、如果同时设置了全局规则和某个类的命名规则,类的命名规则会覆盖全局设置。
1、如果同时设置类的命名规则 和使用 @JsonProperty 在字段上指定序列化名称,则 @JsonProperty 覆盖类上的命名规则。

Jackson 属性自定义命名策略
https://mlog.club/article/5953


@JsonSerialize 自定义序列化器

枚举序列化为小写

使用示例如下:

@JsonInclude(Include.NON_NULL)
public class Bean {
  @JsonSerialize(using = EnumLowerCaseSerializer.class)
  @JsonProperty("inviter_identity")
  private InviterIdentity inviterIdentity;
}

其中
InviterIdentity是自定义枚举类
EnumLowerCaseSerializer是自定义的一个将枚举转化为name小写的转化器,继承自Jackson的JsonSerializer抽象类,重写了其中的serialize()方法

public class EnumLowerCaseSerializer extends JsonSerializer<Enum> {
    @Override
    public void serialize(Enum value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString(value == null ? null : value.name().toLowerCase());
    }
}

Date序列化为时间戳秒

@JsonInclude(Include.NON_NULL)
public class Bean {
  // 创建时间
  @JsonProperty("create_time")
  @JsonSerialize(using = SecondSerializer.class)
  @JsonDeserialize(using = SecondDeserializer.class)
  private Date createTime;
}

其中的Date转换为时间戳秒的序列化类:

package com.masikkk.common.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Date;

public class SecondSerializer extends JsonSerializer<Date> {
    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(date.getTime() / 1000 + "");
    }
}

SpringMVC日期转换之JsonSerialize
https://blog.csdn.net/rendiyiforarchitect/article/details/8056514

自动给Long型字段加一个_str结尾的同值字符串字段

@JsonInclude(Include.NON_NULL)
public class Bean {
  // 用户UUID
  @JsonSerialize(using = LongUUIDSerializer.class)
  private Long uuid;
}

本来uuid是Long型的,可能出现在前后端传输中丢失精度,加上这个序列化类注解后,可自动生成一个名为 uuid_str 的字段,值是 uuid 对应的String类型。

其中的 LongUUIDSerializer 是自定义的序列化器,给注解的Long字段自动加一个 _str 结尾的字符串字段

package com.masikkk.json;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.base.GeneratorBase;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

public class LongUUIDSerializer extends JsonSerializer<Long> {
    // 新增json名称固定后缀
    public final static String jsonNameSuffix = "_str";

    @Override
    public void serialize(Long value, JsonGenerator jsonGenerator, SerializerProvider serializers)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeNumber(value);
        if (jsonGenerator instanceof GeneratorBase) {
            String jsonPropertyName = ((GeneratorBase) jsonGenerator).getOutputContext().getCurrentName();
            jsonGenerator.writeStringField(jsonPropertyName.concat(jsonNameSuffix), String.valueOf(value));
        }
    }
}

@JsonDeserialize 自定义反序列化器

时间戳秒反序列化为Date

@JsonInclude(Include.NON_NULL)
public class Bean {
  // 创建时间
  @JsonProperty("create_time")
  @JsonSerialize(using = SecondSerializer.class)
  @JsonDeserialize(using = SecondDeserializer.class)
  private Date createTime;
}

其中的 SecondDeserializer 是时间戳秒转换为Date的反序列类:

package com.masikkk.common.json;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.util.Date;

public class SecondDeserializer extends JsonDeserializer<Date> {
    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return new Date(Long.parseLong(jsonParser.getText()) * 1000);
    }
}

@JsonFormat 指定String日期格式

import com.fasterxml.jackson.annotation.JsonFormat;

@JsonProperty("create_time")
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;

@JsonProperty("update_time")
@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;

@JsonProperty("update_time")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyyMMddHHmmss", timezone = "GMT+8")
private Date updateTime;

@JsonFormat 和 @DateTimeFormat

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") 用于string日期反序列化为Date,一般前台给后台传值时用
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 用于Date序列化为string

springboot日志和接口返回时间少8小时

一般来说是因为没指定 Jackson 时区

解决:
1、可以在具体字段上指定,如下

@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss", timezone = "GMT+8")
private Timestamp updateTime;

2、objectMapper上设置

@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
    return jacksonObjectMapperBuilder ->
            jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8"));
}

3、在spring中配置
spring.jackson.time-zone=GMT+8


@JsonPropertyOrder 指定字段顺序

@JsonPropertyOrder({ “id”, “label”, “target”, “source”, “attributes” })
public class BeanClass{

}


@JsonCreator 注解反序列化方法

json反序列化为java对象时,该注解用于定义构造函数。当从json创建java时,@JsonCreator注解的构造函数被会调用,如果没有@JsonCreator注解,则默认调用java类的无参构造函数,此时,如果java类中只有有参构造函数,而无默认的无参构造函数,在反序列化时会抛出这样的异常:com.fasterxml.jackson.databind.JsonMappingException,所以,当我们不使用@JsonCreator指定反序列化的构造函数,而又在java类中重载了构造函数时,一定要记得编写类的无参构造函数。

@JsonCreator :反序列化时的构造方法,入参为对应该枚举的json值

public enum VehicleUserRole {

    UNKNOWN((byte) 0, "未知"),
    VehicleUserRole1((byte) 1, "1"),
    VehicleUserRole2((byte) 2, "2"),
    VehicleUserRole3((byte) 3, "3");

    private byte code;
    private String name;

    VehicleUserRole(byte code, String name) {
        this.code = code;
        this.name = name;
    }

    public byte getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    private static Map<Byte, VehicleUserRole> map = Maps.newHashMap();

    static {
        for (VehicleUserRole value : VehicleUserRole.values()) {
            map.put(value.getCode(), value);
        }
        map = Collections.unmodifiableMap(map);
    }

    @JsonCreator
    public static VehicleUserRole getVehicleUserRole(String str) {
        if (StringUtils.isBlank(str)) {
            return UNKNOWN;
        }
        return VehicleUserRole.valueOf(str.trim().toUpperCase());
    }

    public static VehicleUserRole get(byte code) {
        return map.get(code);
    }
}

反序列化构造方法也可以这样写,更稳妥:

@JsonCreator
public static OperatorRole forValue(String nameString) {
    for (OperatorRole operatorRole : OperatorRole.values()) {
        if (operatorRole.name().equalsIgnoreCase(nameString)) {
            return operatorRole;
        }
    }
    return OperatorRole.UNKNOWN;
}

使用处:

@JsonSerialize(using = EnumLowerCaseSerializer.class)
@JsonProperty("vehicle_user_role")
private VehicleUserRole vehicleUserRole;

@JsonValue 注解序列化方法

序列化时,用来生成json值的方法

public enum InviterIdentity {
    UNKNOW((byte) 0, "未知身份"),
    InviterIdentity1((byte) 1, "1"),
    InviterIdentity2((byte) 2, "2"),
    InviterIdentity3((byte) 3, "3");

    private byte code;
    private String name;

    private static Map<Byte, InviterIdentity> codeMap = Maps.newHashMap();

    static {
        for (InviterIdentity inviterIdentity : InviterIdentity.values()) {
            codeMap.put(inviterIdentity.code, inviterIdentity);
        }
        codeMap = Collections.unmodifiableMap(codeMap);
    }

    InviterIdentity(byte code, String name) {
        this.code = code;
        this.name = name;
    }

    public Byte getCode() {
        return code;
    }

    public String getName() {
        return name;
    }

    @JsonValue
    public String getInviterIdentity() {
        return codeMap.get(code).toString().toLowerCase();
    }

    public static InviterIdentity getIdentityByCode(Byte code) {
        return codeMap.get(code);
    }
}

// 使用处
@JsonSerialize(using = EnumLowerCaseSerializer.class)
@JsonProperty("inviter_identity")
private InviterIdentity inviterIdentity;

Jackson 枚举序列化/反序列化
https://blog.csdn.net/z69183787/article/details/54292789


@JsonIgnore 单个字段过滤

@JsonIgnore 注解用来忽略某些字段,可以用在Field或者Getter方法上,用在Setter方法时,和Filed效果一样。这个注解只能用在POJO存在的字段要忽略的情况。

@JsonIgnoreProperties 字段过滤

比如要接收的json字段不固定,或者其中某些字段用不到,可以使用 @JsonIgnoreProperties 做字段过滤

在json转换成的实体类加注解 @JsonIgnoreProperties(ignoreUnknown = true), 注意这是类级别的注解。将这个注解写在类上之后,就会忽略类中不存在的字段,达到按需接受的目的。

这个注解还可以指定要忽略的字段。使用方法如下:
@JsonIgnoreProperties({ “internalId”, “secretKey” })
指定的字段不会被序列化和反序列化。


@JsonInclude指定序列化哪些字段

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;

只序列化非null元素
@JsonInclude(Include.NON_NULL)

只序列化非null和非””元素
@JsonInclude(Include.NON_EMPTY)


其他

字段名不确定如何解析?Map

Gson解析JSON中动态未知字段key的方法
https://blog.csdn.net/Chaosminds/article/details/49049455

java 解析不确定key的json
https://blog.csdn.net/qq_15058425/article/details/56834565

Android json解析动态获取key以及解析技巧
https://blog.csdn.net/u013072976/article/details/43561779

boolean isDone json序列化后成两个字段

// 是否从没购买过
@JsonProperty(“is_never_bought”)
private Boolean neverBought;

public Boolean getNeverBought() {return isNeverBought;}
public void setNeverBought(Boolean neverBought) {isNeverBought = neverBought;}

“never_bought”: true,
“is_never_bought”: true

解决方法,getNeverBought()改为getIsNeverBought()


Direct self-reference leading to cycle 循环自引用

Jackson序列化时报错:

failed to process json obj
com.fasterxml.jackson.databind.JsonMappingException: Direct self-reference leading to cycle (through reference chain:

原因是要序列化的bean中引用了自己,例如:

UserKafkaMessage message = new UserKafkaMessage();
message.setName("xxx");
... ...
message.setBefore(message); // 自己引用了自己

其中 before 字段是 UserKafkaMessage 类型的,本意是要存放user信息变更前的各个字段的值,没想到写代码时写错了直接把 message 自己的引用放进去了,导致出现序列化时 Direct self-reference leading to cycle 错误。


Illegal unquoted character ((CTRL-CHAR, code 10))

背景
spring 对外暴露了一个接口,参数是一个字节数组 image, 正常情况下 image 参数可以接收 base64 编码的图片,自动转换为字节数组

public class FeatureExtractRequest {
    @NotEmpty(message = "image cannot be empty!")
    private byte[] image;
}

问题
调用方调用时,好多图片传入时报错
com.fasterxml.jackson.databind.JsonMappingException: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value
看样子是 Jackson 在将 base64 解码为字节数组时报错了
自己本地也试了下,如果入参 image 不是正确的 base64 编码格式,就会报这个错,比如参数是 {“image”: “dss”} 我们知道 base64 是用4个字符编码3个字节,不足时补=,传入3个字符肯定是错的,就会报这个错。如果换成 {“image”: “dsss”} 四个字符,就没问题了。

原因
经排查,调用方使用了URL格式的base64编码(用下划线_替换/),我本地试了下,正常的4个字符没问题,但如果把其中一个字符换成_,比如 {“image”: “dss_”}, 也会报参数解析错误,但错误提示比较明显,spring默认使用jackson将 base64 反序列化为 byte[], 但使用的是basic的base64编码,不是url的,所以无法识别下划线。

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `byte[]` from String "": Failed to decode VALUE_STRING as base64 (MIME-NO-LINEFEEDS): Illegal character '_' (code 0x5f) in base64 content; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `byte[]` from String "": Failed to decode VALUE_STRING as base64 (MIME-NO-LINEFEEDS): Illegal character '_' (code 0x5f) in base64 content

解决
调用方把base64编码格式改为basic的之后好了。


上一篇 Cassandra笔记

下一篇 接下来要学习的

阅读
评论
4.2k
阅读预计19分钟
创建日期 2018-08-16
修改日期 2021-07-12
类别
目录
  1. 变量命名方式
    1. Lower Camel Case 小驼峰式
    2. Upper Camel Case 大驼峰/Pascal
    3. Snake Case 蛇式(下划线分割)
    4. Kebab Case 烤肉式(中线分割)
  2. Jackson 版本和依赖包
    1. Jackson 2.x(fasterxml)主要依赖包
    2. Jackson 1.x(codehaus)主要依赖包
  3. ObjectMapper 配置
    1. 关闭 FAIL_ON_EMPTY_BEANS
    2. 关闭 FAIL_ON_UNKNOWN_PROPERTIES
    3. JsonInclude.Include.NON_NULL
    4. INDENT_OUTPUT缩进美化输出
  4. Jackson枚举反序列化大小写无关
  5. ObjectMapper 常用方法
    1. writeValueAsString() 序列化
    2. readValue() 反序列化
      1. Json串转Java Map对象
    3. convertValue() 类型转换
      1. Java Object和Map互转
    4. writerWithDefaultPrettyPrinter() 漂亮打印
    5. copy() 拷贝实例
  6. TypeReference 泛型反序列化
  7. Jackson 常用注解
    1. @JsonProperty 字段与成员变量映射
    2. @JsonNaming 序列化命名策略
    3. @JsonSerialize 自定义序列化器
      1. 枚举序列化为小写
      2. Date序列化为时间戳秒
      3. 自动给Long型字段加一个_str结尾的同值字符串字段
    4. @JsonDeserialize 自定义反序列化器
      1. 时间戳秒反序列化为Date
    5. @JsonFormat 指定String日期格式
      1. @JsonFormat 和 @DateTimeFormat
      2. springboot日志和接口返回时间少8小时
    6. @JsonPropertyOrder 指定字段顺序
    7. @JsonCreator 注解反序列化方法
    8. @JsonValue 注解序列化方法
    9. @JsonIgnore 单个字段过滤
    10. @JsonIgnoreProperties 字段过滤
    11. @JsonInclude指定序列化哪些字段
  8. 其他
    1. 字段名不确定如何解析?Map
    2. boolean isDone json序列化后成两个字段
    3. Direct self-reference leading to cycle 循环自引用
    4. Illegal unquoted character ((CTRL-CHAR, code 10))

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论