美文网首页springboot
spring boot之json实战

spring boot之json实战

作者: 松松土_0b13 | 来源:发表于2019-08-22 18:03 被阅读0次

json是web应用中最常用的通讯格式,应用场景之多,json的序列化工具也炒鸡多,粗略测试下来,执行效率 gson > fastjson > jackson,这里以gson的2.8.5版本为例

使用Gson替换Jackson

Jackson一直是springframework默认的json库,从4.1开始,springframework支持通过配置GsonHttpMessageConverter的方式使用Gson

import com.google.gson.*;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.GsonHttpMessageConverter;

import java.lang.reflect.Type;

/**
 * @描述:
 * @公司:
 * @版本: 1.0.0
 * @日期: 2019年08月21日 17:40
 */
@Configuration
public class GsonConfig {

    @Bean
    public Gson gson(){
        return new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
            .registerTypeAdapter(String.class,new SpringfoxJsonToGsonAdapter()).create();
    }

    @Bean
    public HttpMessageConverters httpMessageConverters() {
        GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
        gsonHttpMessageConverter.setGson(gson());
        return new HttpMessageConverters(gsonHttpMessageConverter);
    }

    public class SpringfoxJsonToGsonAdapter implements JsonSerializer<String> {

        @Override
        public JsonElement serialize(String json, Type type, JsonSerializationContext jsonSerializationContext) {
            return new JsonParser().parse(json);
        }
    }
}

可以自己定制时间日期的序列化格式

gson工具类转换

/**
 * @描述:
 * @公司:
 * @版本: 1.0.0
 * @日期: 2019年08月16日 08:59
 */
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.internal.$Gson$Types;
import com.google.gson.reflect.TypeToken;
import org.springframework.beans.BeanUtils;


public class GsonUtils {
    //不用创建对象,直接使用Gson.就可以调用方法
    private static Gson gson = null;
    //判断gson对象是否存在了,不存在则创建对象
    static {
        if (gson == null) {
            //gson = new Gson();
            //当使用GsonBuilder方式时属性为空的时候输出来的json字符串是有键值key的,显示形式是"key":null,而直接new出来的就没有"key":null的
            gson= new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        }
    }
    //无参的私有构造方法
    private GsonUtils() {
    }
    /**
     * 将对象转成json格式
     *
     * @param object
     * @return String
     */
    public static String GsonString(Object object) {
        String gsonString = null;
        if (gson != null) {
            gsonString = gson.toJson(object);
        }
        return gsonString;
    }

    /**
     * 将json转成特定的cls的对象
     *
     * @param gsonString
     * @param cls
     * @return
     */
    public static <T> T GsonToBean(String gsonString, Class<T> cls) {
        T t = null;
        if (gson != null) {
            //传入json对象和对象类型,将json转成对象
            t = gson.fromJson(gsonString, cls);
        }
        return t;
    }

    /**
     * json字符串转成list
     *
     * @param gsonString
     * @param cls
     * @return
     */
    public static <T> List<T> GsonToList(String gsonString, Class<T> cls) {
        List<T> list = null;
        if (gson != null) {
            Type type = $Gson$Types.newParameterizedTypeWithOwner(null, ArrayList.class, cls);
            list = gson.fromJson(gsonString, type);
        }
        return list;
    }

    /**
     * json字符串转成list中有map的
     *
     * @param gsonString
     * @return
     */
    public static <T> List<Map<String, T>> GsonToListMaps(String gsonString) {
        List<Map<String, T>> list = null;
        if (gson != null) {
            list = gson.fromJson(gsonString,
                    new TypeToken<List<Map<String, T>>>() {
                    }.getType());
        }
        return list;
    }

    /**
     * json字符串转成map的
     *
     * @param gsonString
     * @return
     */
    public static <T> Map<String, T> GsonToMaps(String gsonString) {
        Map<String, T> map = null;
        if (gson != null) {
            map = gson.fromJson(gsonString, new TypeToken<Map<String, T>>() {
            }.getType());
        }
        return map;
    }
}

gson序列化总结

  • gson在将json字符串序列化为list的bean的时候,用TypeToken的方式有bug,上面的示例代码,已经修复了这个bug
  • gson在序列化的时候,可以给bean加注解,以实现一些功能
@SerializedName(value = "emailAddress", alternate = { "email", "email_address" })
private String emailAddress;

当上面的三个属性(email_address、email、emailAddress)中都出现,或出现任意一个时均可以得到正确的结果。
注:当多种情况同时出时,以最后一个出现的值为准。

  • 自定义字段的名字
@SerializedName("w");
int width

这个注解可以用来自定义序列化和反序列化过程中字段的名字。
以上面为例,当序列化的时候,会把Java bean中的字段width存储成w,在反序列化的时候会把Json的w这个key反序列化到Java bean的width字段上

序列化扩展-两个实体类转换

  • 用BeanUtils或者PropertyUtils的copyProperties,同名属性不同类型,PropertyUtils会报错
  • Spring 中的BeanUtils与apache中的BeanUtils都可以用,但是推荐使用Spring,同名属性一个属性为日期类型,Spring会直接忽视,apache在做日期转换时会有问题,问题情况比较多,这里不做细分了
/**
 * 实体类转字体类
 * @param source 源实体类
 * @param cls
 * @return
 */
public static <T> T gsonBean2(Object source, Class<T> cls){
    T t = null;
    if (source !=null && gson != null) {
        //创建泛型类的实例
        try {
            t=cls.newInstance();
            BeanUtils.copyProperties(source,t);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return t;
}

/**
 * 实体类list转字体类list, List<?>是type-safe
 * @param sourceList 源实体类
 * @param cls
 * @return
 */
public static <T> List<T> gsonBeanList2(List<?> sourceList, Class<T> cls){
    List<T> list = null;
    if (sourceList !=null && gson != null) {
        list = new ArrayList<T>();
        //创建泛型类的实例
        try {
            for(Object source : sourceList){
                T t = cls.newInstance();
                BeanUtils.copyProperties(source,t);
                list.add(t);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return list;
    }

相关文章

网友评论

    本文标题:spring boot之json实战

    本文链接:https://www.haomeiwen.com/subject/ejznsctx.html