4. FastJson序列化对象中非字符串类型key输出非标准格式json串问题记录

一灰灰blogJava问题记录FastJson约 534 字大约 2 分钟

采用fastjson作为项目的json序列化和反序列化工具,遇到一个蛋疼至极的问题, 如Map,key为int,则输出的字符串中,key没有被双引号括起来,导致前端解析失败

1. 问题复现

环境相关

jdb1.8


<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.45</version>
</dependency>

测试case

@Test
public void testJson() {
    Map<Integer, String> ans = new HashMap<>();
    ans.put(10, "hello");
    ans.put(20, "world");

    System.out.println("fastjson: " + JSON.toJSONString(ans));

    Gson gson = new Gson();
    System.out.println("gson: " + gson.toJson(ans));
}

为了对比,把gson也加进来了,输出结果如下

fastjson: {20:"world",10:"hello"}
gson: {"20":"world","10":"hello"}

针对fastjson的输出,js的序列化直接异常

IMAGE
IMAGE

2. 兼容方案

既然fastjson有这个问题,那有必要看一下有没有使用方式来避免这个问题了,看一下fastjson的常用序列化方法

/**
 * This method serializes the specified object into its equivalent Json representation. Note that this method works fine if the any of the object fields are of generic type,
 * just the object itself should not be of a generic type. If you want to write out the object to a
 * {@link Writer}, use {@link #writeJSONString(Writer, Object, SerializerFeature[])} instead.
 *
 * @param object the object for which json representation is to be created setting for fastjson
 * @return Json representation of {@code object}.
 */
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);
}

/**
 * @since 1.2.11
 */
public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features) {
    SerializeWriter out = new SerializeWriter((Writer) null, defaultFeatures, features);

    try {
        JSONSerializer serializer = new JSONSerializer(out);
        serializer.write(object);
        return out.toString();
    } finally {
        out.close();
    }
}

我们常用的是上面的第一个方法,看到上面的第二个方法,自然可以想到,是不是可以通过传参来设置序列化的一些属性, SerializerFeature 是一个枚举,进去查看,会找到一些有意思的参数,如SerializerFeature.WriteNonStringKeyAsString将非字符串的key装换为String

@Test
public void testJson() {
    Map<Integer, String> map = new HashMap<>();
    map.put(1, "hello");
    map.put(2, "world");
    System.out.println(JSON.toJSONString(map));

    // 如果key不是字符串,则序列化为字符串
    System.out.println(JSON.toJSONString(map, SerializerFeature.WriteNonStringKeyAsString));
}

输出结果如下

IMAGE
IMAGE
Loading...