[alibaba/fastjson]序列化FileSystemResource导致文件内容丢失

2024-09-20 771 views
5
问题描述

有个功能需要调用一个传输文件的api,使用FileSystemResource进行传输,在调用api之前使用JSONObject.toJSONString()输出一下log,结果发现每次输出log之后本地文件就会变成0KB。

版本
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.72</version>
</dependency>
问题复现
  • 随便创建了一个txt文件写点内容
  • demo代码如下
    HashMap<String, Object> hashMap = new HashMap<>();
    FileSystemResource fileSystemResource = new FileSystemResource("E:\\my-code\\test\\test-fastjson.txt");
    System.out.println("file size before Serialize:" + fileSystemResource.getFile().length());
    hashMap.put("id",1);
    hashMap.put("file",fileSystemResource);
    System.out.println(JSONObject.toJSONString(hashMap));
    System.out.println("file size after Serialize:" + fileSystemResource.getFile().length());
  • 运行结果:
    file size before Serialize:25
    {"file":{"description":"file [E:\\my-code\\test\\test-fastjson.txt]","file":"E:\\my-code\\test\\test-fastjson.txt","filename":"test-fastjson.txt","open":false,"outputStream":{},"path":"E:/my-code/test/test-fastjson.txt","readable":true,"uRI":"file:/E:/my-code/test/test-fastjson.txt","uRL":"file:/E:/my-code/test/test-fastjson.txt","writable":true},"id":1}
    file size after Serialize:0

回答

1

the reason for this problem is that the instantiation of this interface ObjectSerializer is based on the map valuel type. And the "fileSystemResource" is instantiated as MiscCodec class because it is a file type and execute this method as " com.alibaba.fastjson.serializer$MiscCodec#write(line:111)" and will only rewrite the file name according to the file path, and lose the file content.But if the map value is a string type, it is instantiated as StringCodec class and the source file will not be changed. Therefore, if you want to avoid this problem, you can replace "hashMap.put("file",fileSystemResource)" with “hashMap.put("file",fileSystemResource.getFile().getAbsolutePath()” and they are the same for printing logs. Thanks!

3
public class Issue3436 extends TestCase {
    public void test_for_issue() throws Exception {
        JSON.addMixInAnnotations(FileSystemResource.class, FileSystemResourceMixedIn.class);

        FileSystemResource fileSystemResource = new FileSystemResource("E:\\my-code\\test\\test-fastjson.txt");

        String json = JSON.toJSONString(fileSystemResource);
        assertEquals("{\"path\":\"E:/my-code/test/test-fastjson.txt\"}", json);

        FileSystemResource fsr1 = JSON.parseObject(json, FileSystemResource.class);
        assertEquals(fileSystemResource.getPath(), fsr1.getPath());
        System.out.println("file size after Serialize:" + fileSystemResource.getFile().length());
    }

    @JSONType(asm = false, includes = "path")
    public static class FileSystemResourceMixedIn {
        @JSONCreator
        public FileSystemResourceMixedIn(String path) {

        }
    }
}
8

FileSystemResource 实现了WritableResource 中的 OutputStream getOutputStream() throws IOException; 被fastJson 调用了,在构造OutputStream的时候清空了文件

看这里吧,这里解释清楚了