简介:
序列化:
顾名思义就是将你所需要操作的实体及属性按照指定的顺序进行操作执行
反序列化:
将序列化操作的字段或实体属性进行还原操作
注意:使用的是哪个的就必须一直使用那个,不然会导致不必要的引用问题
测试用例模拟:
测试实体属性
@Data
@AllArgsConstructor
public class JsonBean {
@JsonProperty(value = "fasterxml_name1")
@JSONField( name = "alibaba_name1")
@SerializedName("google_name1")
@JsonSerialize(using = JackCustomStringSerializer.class)
// @JsonSerialize(using = )
// 3 种对应的 自定义序列化
private String name;
@JsonProperty("fasterxml_sex1")
@JSONField( name = "alibaba_sex1",serializeUsing = AlibabaCustomStringSerializer.class)
@SerializedName(value = "google_sex1")
private String sex;
// @JSONField(format = "yyyy-MM-dd HH:mm:ss")
@JsonSerialize(using = JacksonJsonSerializer.class)
@JSONField(serializeUsing = AlibabaSerializer.class)
private Date createTime;
/* @JsonSerialize(contentUsing = JacksonJsonSerializer.class)
private List<Date> dates;*/
}
测试用例
public class JsonDemo {
public static void main(String[] args) throws JsonProcessingException {
JsonBean jsonBean = new JsonBean("Brain","Male",new Date());
/* SerializeConfig config = new SerializeConfig();
config.put(Date.class, new AlibabaSerializer());*/
// System.out.println("alibaba json:" + JSON.toJSONString(jsonBean, config));
System.out.println("alibaba json:" + JSON.toJSONString(jsonBean));
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new GoogleJsonSerializer())
.registerTypeAdapter(String.class, new GoogleCustomStringSerializer())
.create();
System.out.println("google json:" + gson.toJson(jsonBean));
System.out.println("fasterxml json:" + new ObjectMapper().writeValueAsString(jsonBean));
}
}
@JSONField
主要用于返回出参转换
这个注解分别可以注解在实体类的属性、setter和getter方法上
public class Test{
/*
注解在属性上的时候可以设置一些序列化、格式化的属性
@JSONField(serialize = false)---->序列化的时候忽略这个属性
@JSONField(format = "yyyyMMdd")---->序列化和反序列化额时候使用yyyyMMdd,一般在Date类型的字段上使用
*/
@JSONField(serialize = false)
public String Name;
/*
注解在set方法表示json转成bean的时候会将json中的Name属性赋值给实体类的Name
*/
@JSONField(name="Name")
public void setName(String Name){this.Name = Name;}
/*
注解在get方法表示bean转换成json的时候会把实体类的Name属性值赋给json的Name
*/
@JSONField(name="Name")
public String getName(){return this.Name;}}
自定义序列化方法实现:
date类型
public class AlibabaSerializer implements ObjectSerializer {
/*
所有的Date类型的字段在序列化的时候都会被转化为时间戳,再加上"-custom"的后缀。
*/
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter out = serializer.out;
if (object == null) {
out.writeNull();
return;
}
Date date = (Date) object;
String text = date.getTime() + "-custom"; // 自定义序列化格式
out.writeString(text);
}
}
String类型
public class CustomStringSerializer implements ObjectSerializer {
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
// 在这里实现你对String的定制序列化逻辑
serializer.write(object.toString().toUpperCase());
}
}
引用实现:
@JSONField( name = "alibaba_sex1",serializeUsing = CustomStringSerializer.class)
@JSONField(serializeUsing = AlibabaSerializer.class)
反序列化的实现:
采用阿里的@JSONField进行时间格式的自定义反序列化的操作来实现学习、测试、生产等方面的应用(下同)
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CustomSerializationTest3 {
// 定义自定义的日期序列化器
public static class CustomDateSerializer implements ObjectSerializer {
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
public CustomDateSerializer() {
// 默认构造函数
}
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
Date date = (Date) object;
String dateFormatAsString = date != null ? format.format(date) : null;
serializer.write(dateFormatAsString);
}
}
// 定义自定义的日期反序列化器
public static class CustomDateDeserializer implements ObjectDeserializer {
private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
public CustomDateDeserializer() {
// 默认构造函数
}
@Override
public <T> T deserialze(com.alibaba.fastjson.parser.DefaultJSONParser parser, Type type, Object fieldName) {
String dateStr = parser.getLexer().stringVal();
try {
return (T) format.parse(dateStr);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
@Override
public int getFastMatchToken() {
return 0;
}
}
// 用户类
@Data
@NoArgsConstructor
@AllArgsConstructor
public static class User {
private String name;
@JSONField(serializeUsing = CustomDateSerializer.class, deserializeUsing = CustomDateDeserializer.class)
private Date birthday;
}
// 单元测试类
@Test
public void testCustomSerialization() {
User user = new User("John Doe", new Date());
// 序列化
String json = JSON.toJSONString(user);
System.out.println(json);
// 反序列化
User deserializedUser = JSON.parseObject(json, User.class);
System.out.println(deserializedUser.getBirthday());
}
}
运行结果:
@JsonProperty
主要用于入参转换,和Json字符串序列化为Java对象
@JsonProperty
是com.fasterxml.jackson.annotation
下使用频率很高的一个常用注解,用于将json字符串中的某个字段和java对象中的某个属性进行匹配映射,同时可以将java对象中的属性转换为指定字段的json字符串。
在java属性上加上@JsonProperty注解:
@JsonProperty("jsonName")
private String name;
测试
@Test
public void testJsonProperty() throws IOException{
String jsonBean1 = "{\"jsonName\":\"xyz\",\"age\":\"12\",\"address\":\"china\"}";
ObjectMapper mapper = new ObjectMapper();
Object myBean1 = mapper.readerFor(MyBean.class).readValue(jsonBean1);
System.err.println("Convert json to java: "+ myBean1.toString());
MyBean myBean = new MyBean("xyz", "China", 12);
System.err.println("Conver java to json: " + mapper.writeValueAsString(myBean));}
运行结果
自定义序列化实现:
Date类型
public class JacksonJsonSerializer extends com.fasterxml.jackson.databind.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);
}
}
String类型
public class CustomStringSerializer extends JsonSerializer<String> {
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 这里你可以对value做你需要的处理
gen.writeString(value.toUpperCase());
}
}
引用实现
@JsonSerialize(using = CustomStringSerializer.class)
@JsonSerialize(using = JacksonJsonSerializer .class)
注意:JsonSerialize中有using、contentUsing、keyUsing、nullsUsing;分别使用的场景是值、集合/数组、map集合、定制的null序列化器,如果检测到null,它会输出字符串"NULL";
反序列化的实现:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.util.StdConverter;
import junit.framework.TestCase;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
// 单元测试类
public class CustomSerializationTest extends TestCase {
@Data
@NoArgsConstructor
@AllArgsConstructor
static class User {
@JsonProperty("username")
private String name;
@JsonProperty("userdate")
@JsonSerialize(using = JacksonJsonSerializer.class) // 如果需要特定格式的字符串,可以使用自定义序列化器
@JsonDeserialize(converter = StringToDateConverter.class)
private Date dateOfBirth;
}
//日期格式序列化
static class JacksonJsonSerializer extends com.fasterxml.jackson.databind.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);
}
}
//日期格式反序列化
static class StringToDateConverter extends StdConverter<String, Date> {
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
public Date convert(String value) {
try {
return value == null ? null : dateFormat.parse(value);
} catch (Exception e) {
// Ideally, you'd handle this a bit more gracefully
throw new RuntimeException(e);
}
}
}
@Test
public void test() {
try {
User user = new User("John Doe",new Date());
ObjectMapper mapper = new ObjectMapper();
String serializedUser = mapper.writeValueAsString(user);
System.out.println("Serialized User: " + serializedUser);
User deserializedUser = mapper.readValue(serializedUser, User.class);
System.out.println("Deserialized User's Date of Birth: " + deserializedUser.getDateOfBirth());
// 此处可以添加更多的测试和验证逻辑
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
@SerializedName
@SerializedName
是com.google.gson.annotations
下的常用注解,作用和@JsonProperty
差不多,重点是可以将多个字段名称映射到一个字段属性上
SerializedName 改变了默认序列化和默认反序列化的字段取值,所以,如果你使用 Gson 将 Java model 类生称 JSON 串,结果就是 value 的名称就是字段的名称。
SerializedName 接受两个参数,value、alternate,第一个value是默认参数,如果你只填了一个参数,那这个值将会赋值给 value。
alternate 属性是用在反序列化上的,也就是说从 JSON 到 Java 类的过程。Gson 会帮我们匹配 JSON 中的命名,并尝试找到一个字段映射。无论哪一个都会映射。
在java属性上加上@SerializedName注解:
@SerializedName("jsonName", alternate = "json_name, json")
private String name;
测试
@Test
public void testFromJeson() throws IOException {
String jsonBean1 = "{\"jsonName\":\"xyz\",\"age\":\"12\",\"address\":\"china\"}";
MyBean myBean = new MyBean("xyz", "China", 12);// 注意:写法和@JsonProperty不同
Gson gson = new Gson();
MyBean myBean1 = gson.fromJson(jsonBean1, MyBean.class);
System.err.println("jesonBean1: "+ myBean1.toString());
String toJson = gson.toJson(myBean);
System.err.println("toJson: " + toJson);
}
运行结果
自定义序列化方法实现:
Date类型
public class GoogleJsonSerializer implements JsonSerializer<Date> {
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
return new JsonPrimitive(formatter.format(src));
}
}
String类型
public class GoogleCustomStringSerializer implements JsonSerializer<String> {
@Override
public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.toUpperCase());
}
}
引用实现:
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, new GoogleJsonSerializer())
.registerTypeAdapter(String.class, new GoogleCustomStringSerializer())
.create();
反序列化的实现:
import com.google.gson.*;
import com.google.gson.annotations.SerializedName;
import org.junit.Test;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CustomSerializationTest {
// 定义User类
public static class User {
@SerializedName("custom_name")
private String name;
@SerializedName("custom_date")
private Date date;
public User(String name, Date date) {
this.name = name;
this.date = date;
}
public String getName() {
return name;
}
public Date getDate() {
return date;
}
}
// 自定义的日期序列化器
public class CustomDateSerializer implements JsonSerializer<Date> {
private final DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(format.format(src));
}
}
// 自定义的日期反序列化器
public class CustomDateDeserializer implements JsonDeserializer<Date> {
private final DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
try {
return format.parse(json.getAsString());
} catch (Exception e) {
return null;
}
}
}
@Test
public void testCustomSerialization() {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new CustomDateSerializer());
builder.registerTypeAdapter(Date.class, new CustomDateDeserializer());
Gson gson = builder.create();
User user = new User("Test", new Date());
String jsonString = gson.toJson(user);
System.out.println(jsonString);
User deserializedUser = gson.fromJson(jsonString, User.class);
System.out.println(deserializedUser.getName());
}
}