美文网首页
Fastjson 基础

Fastjson 基础

作者: Tinyspot | 来源:发表于2023-02-18 07:42 被阅读0次

1. Fastjson 简介

  • 包:com.alibaba.fastjson.*
  • JSON 类里基本都是静态方法

2. JSON 类

image.png
public abstract class JSON implements JSONStreamAware, JSONAware {

    public static String toJSONString(Object object) {
        return toJSONString(object, emptyFilters);
    }
    public static String toJSONString(Object object, SerializerFeature... features) {
        return toJSONString(object, DEFAULT_GENERATE_FEATURE, features);
    }

    public static String toJSONStringWithDateFormat(Object object, String dateFormat, SerializerFeature... features) {
        return toJSONString(object, SerializeConfig.globalInstance, null, dateFormat, DEFAULT_GENERATE_FEATURE, features);
    }

    public static <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
        return (T) parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
    }
}

2.1 JSON串序列化与反序列化

@Test
public void test() {
    // 序列化
    String jsonStr = JSON.toJSONString(new Order(1001L, "R001"));
    // 反序列化
    Order order = JSON.parseObject(jsonStr, Order.class);
}

2.2 日期处理

toJSONString() 会将日期转成时间戳

@Test
public void test() {
    Order order = new Order(1001L, "R001", new Date());
    String jsonStr = JSON.toJSONString(order);

    // 日期格式化
    String jsonDateStr = JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss");
}

打印结果
jsonStr: {"code":"R001","date":1676694709297,"id":1001}
jsonDateStr: {"code":"R001","date":"2023-02-18 12:31:49","id":1001}

3. JSONObject

public abstract class JSON implements JSONStreamAware, JSONAware {
    public static JSONObject parseObject(String text) {
    }

    public static <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
        return (T) parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
    }
}

3.1 对象互转

  1. JSON串 --> JSONObject
    JSONObject jsonObj = JSON.parseObject(jsonStr);

  2. Java 对象 --> JSONObject
    JSONObject jsonObj = JSON.parseObject(JSON.toJSONString(order));

  3. JSONObject --> Java 对象
    Order order = JSON.parseObject(jsonStr, Order.class);

  4. JSON串 --> Java 对象(带泛型)

@Test
public void test() {

    OrderDTO order = new OrderDTO(1001L, "R001", new Date());
    ResultDTO<OrderDTO> resultDTO = new ResultDTO<>(order, true);
    String jsonStr = JSON.toJSONString(resultDTO);
    // {"data":{"code":"R001","date":1676695213857,"id":1001},"success":true}

    // 带泛型
    ResultDTO<OrderDTO> result = JSON.parseObject(jsonStr, new TypeReference<ResultDTO<OrderDTO>>() {});
}
@Data
@AllArgsConstructor
public class ResultDTO<T> {
    private T data;
    private boolean success;
}

@Data
@AllArgsConstructor
public class OrderDTO {
    private Long id;
    private String code;
    private Date date;
}

3.2 JSONObject 源码

public class JSONObject extends JSON implements Map<String, Object>, Cloneable, Serializable, InvocationHandler {
    private final Map<String, Object> map;

    public JSONObject(){
        this(DEFAULT_INITIAL_CAPACITY, false);
    }
    public JSONObject(int initialCapacity, boolean ordered){
        if (ordered) {
            map = new LinkedHashMap<String, Object>(initialCapacity);
        } else {
            map = new HashMap<String, Object>(initialCapacity);
        }
    }
    
    public Object put(String key, Object value) {
        return map.put(key, value);
    }
}

JSONObject 实现 Map 接口,而且定义了一个map字段,在初始化的时候可根据是否需要有序来初始化为 LinkedHashMap 或者 HashMap
JSONObject 相当于一个 Map,当操作 JSONObject 的时候,其实是调用了Map的方法

4. JSONArray

  1. JSON串 --> JSONArray
    JSONArray jsonArray = JSON.parseArray(jsonStr);

  2. JSON串 --> List
    List<Order> orderList = JSON.parseArray(jsonStr, Order.class);

  3. List --> JSONArray

@Test
public void test() {
    List<String> list = Arrays.asList("aaa", "bbb");
    JSONArray array = JSON.parseArray(JSON.toJSONString(list));
    List<String> strings = JSON.parseArray(JSON.toJSONString(list), String.class);
}

4.2 反例

注意不要用 JSONObject.parseObject() 来转换 List

@Test
public void test() {
    String jsonStr = "[{\"code\":\"R001\",\"date\":1676703926184,\"id\":1001},{\"code\":\"R002\",\"date\":1676703926184,\"id\":1002}]";

    // Unchecked assignment: 'java.util.List' to 'java.util.List<com.example.concrete.starter.pojo.Order>'
    List<Order> orderList = JSONObject.parseObject(jsonStr, List.class);
    System.out.println(orderList + "; " + orderList.get(0)); // 正常打印

    System.out.println(orderList.get(0).getCode()); // 异常
}

分析
orderList.get(0).getCode() 报错:java.lang.ClassCastException,因为 orderList 实际是 ArrayList<JSONObject>,并未转为真正需要的泛型 List<Order>

5. 泛型处理(TypeReference)

JSON串转为 Map,含有泛型的 JSON 反序列化

5.1 JSON串 --> Map<String, Object>

@Test
public void test() {
    Map<String, Order> orderMap = new HashMap<String, Order>(){{
        put("001", new Order(1001L, "T001"));
        put("002", new Order(1002L, "T002"));
    }};
    String jsonStr = JSON.toJSONString(orderMap);

    // 没有泛型 是不安全的
    Map map = JSON.parseObject(jsonStr);

    // TypeReference 但构造方法是protected,所以使用它的子类
    // 用匿名内部类作为 TypeReference 子类
    TypeReference<Map<String, Order>> typeReference = new TypeReference<Map<String, Order>>() {};
    Map<String, Order> result = JSON.parseObject(jsonStr, typeReference);
}

5.2 JSON串 --> Map<String, List<Object>>

@Test
public void test() {

    Map<Integer, List<Order>> data = new HashMap<Integer, List<Order>>() {{
        put(2022001, Arrays.asList(new Order(1001L, "T001")));
        put(2022002, Arrays.asList(new Order(1002L, "T002")));
    }};
    String jsonStr = JSON.toJSONString(data);

    Map<Integer, List<Order>> map = JSON.parseObject(jsonStr, new TypeReference<Map<Integer, List<Order>>>() {});

    // 方式一:使用 Type
    Type type = new TypeReference<Map<Integer, List<Order>>>(){}.getType();
    Map<Integer, List<Order>> resultMap = JSON.parseObject(jsonStr, type);

    // 方式二
    Map<Integer, List<Order>> integerListMap = JSON.parseObject(jsonStr, new TypeReference<Map<Integer, List<Order>>>() {});

}

5.3 解析泛型对象

@Test
public void test() {
    String jsonStr = "{\"data\":{\"code\":\"R001\",\"date\":1676695213857,\"id\":1001},\"success\":true}";
    ResultDTO<OrderDTO> result = JSON.parseObject(jsonStr, new TypeReference<ResultDTO<OrderDTO>>() {});

    jsonStr = "{2022002:[{\"code\":\"T002\",\"id\":1002}],2022001:[{\"code\":\"T001\",\"id\":1001}]}";
    Map<Integer, List<Order>> map = JSON.parseObject(jsonStr, new TypeReference<Map<Integer, List<Order>>>(){});

}

5.2 TypeReference 源码分析

public class TypeReference<T> {
        // 构造方法是 protected,包外若要创建对象只能使用子类
        protected TypeReference(){
        Type superClass = getClass().getGenericSuperclass();

        Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];

        Type cachedType = classTypeCache.get(type);
        if (cachedType == null) {
            classTypeCache.putIfAbsent(type, type);
            cachedType = classTypeCache.get(type);
        }

        this.type = cachedType;
    }
}

用匿名内部类作为 TypeReference 子类
TypeReference<Map<String, Object>> typeReference = new TypeReference<Map<String, Object>>() {};

5.3 对象拷贝

方式一:import org.springframework.beans.BeanUtils;
BeanUtils.copyProperties(dataDTO, dataTarget);
缺点:受限于属性类型,比如 Long 类型无法赋值给 String 类型

方式二:
DataTarget target = JSON.parseObject(JSON.toJSONString(dataDTO), DataTarget.class);

6. JSON 遍历

public static void main(String[] args) {
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("key", "value");
    for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
        
    }
    for (String s : jsonObject.keySet()) {
        
    }

    String str = "{\"users\":[{\"name\":\"tinyspot\",\"age\":20},{\"name\":\"xing\",\"age\":25}]}";
    Map<String, List<User>> userMap = JSON.parseObject(str, new TypeReference<Map<String, List<User>>>(){});
    for (Map.Entry<String, List<User>> entry : userMap.entrySet()) {
        for (User user : entry.getValue()) {
            System.out.println(user.getName() + "; " + user.getAge());
        }
    }
}

相关文章

网友评论

      本文标题:Fastjson 基础

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