是否可以控制JacksonSmile数据格式序列化中字段顺序

f1tvaqid  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(122)

我有一个简单的Java类looks like this

public class AnnotationData implements Serializable {

    public AnnotationData(String filename) {
        this.filename = filename;
    }

    private List<AnnotationLine> annotationLines = new ArrayList<>();

    private int widestRevision;

    private int widestAuthor;

    private String filename;

    private String revision;

    // getters and setters for the above fields omitted
}

AnnotationLine是另一个简单的Serializable类,有3个字段(字符串、字符串、布尔值)。
AnnotationData类的示例使用Jackson中的Smile数据格式进行序列化和反序列化:

private void writeCache(AnnotationData annotationData, File outfile) throws IOException {
        ObjectMapper mapper = new SmileMapper();
        mapper.writeValue(outfile, annotationData);
}

static Annotation readCache(File file) throws IOException {
        ObjectMapper mapper = new SmileMapper();
        return new Annotation(mapper.readValue(file, AnnotationData.class));
}

在某些情况下,我希望避免阅读整个文件(特别是可能很长的annotationLines列表),而只读取revision字段。
查看示例的编码,可以看到revision字段位于文件开头附近:

0000000   :   )  \n 001   � 215   w   i   d   e   s   t   R   e   v   i
0000010   s   i   o   n   � 213   w   i   d   e   s   t   A   u   t   h
0000020   o   r   $   � 207   f   i   l   e   n   a   m   e   G   c   l
0000030   i   e   n   t   .   c 207   r   e   v   i   s   i   o   n   Q
0000040   1   5   4   3   1   :   5   b   1   8   b   4   1   4   4   5
0000050   8   2 204   l   i   n   e   s   �   �   C   @   0 205   a   u
0000060   t   h   o   r   P   s   t   e   v   e   l   @   t   o   n   i
...
00126b0   3   1   C   6   0   3   5   C   5   7   7   7   B   4   0   7
00126c0   �   �                                                        
00126c2

这实际上是我所需要的,但是需要一些订购的保证。
所以,我的问题有两个部分:

  • 是否可以控制编码文件中特定字段的位置,例如,通过JacksonJava注解(原文如此)?(即,确保首先序列化某些字段)
  • 假设是的话,那么只反序列化该字段的代码是什么呢?(这样可以避免遍历整个文件)

欢迎使用代码示例。

brjng4g3

brjng4g31#

首先,使用以下注解确保AnnotationData中的revision字段序列化为第一个字段:

@JsonPropertyOrder({"revision"})

可以指定多个字段,这里一个就足够了。
接下来,直接使用解析器读取revision字段的值:

SmileFactory factory = new SmileFactory();
        try (SmileParser parser = factory.createParser(file)) {
            parser.nextToken();
            while (parser.getCurrentToken() != null) {
                if (parser.getCurrentToken().equals(JsonToken.FIELD_NAME)) {
                    break;
                }
                parser.nextToken();
            }

            if (parser.getCurrentName().equals("revision")) {
                parser.nextToken();
                if (!parser.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
                    return null;
                }
                return parser.getValueAsString();
            } else {
                return null;
            }
        }

请记住,Jackson默认使用8000字节的读取缓冲区,因此这将仅在较大的文件上保存I/O。

相关问题