在枚举反序列化期间寻找这种奇怪行为的解释

时间:2019-01-07 11:43:29

标签: java jsonb-api

最近,在将枚举反序列化到JSON或从JSON反序列化期间,我遇到了一种奇怪的行为。

我将相关部分简化为一个简单的示例(请参见下面的代码)。基本上,您有一个包含枚举条目的列表。您序列化列表,然后反序列化它。如果您检查新的(反序列化的)列表(如果其中包含某些枚举项),则即使该列表实际上包含该条目,您也将始终得到“ false”作为答案。

我自己分析了一下之后发现,将列表反序列化后,内容不再是枚举类型,而是包含字符串。

我想了解为什么会发生这种情况以及如何避免这种情况。我的目标是在反序列化之后再次列出一个枚举条目,而不是一个字符串列表。

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;

public class Test {

    enum TYPE {
        SMALL, MEDIUM, LARGE
    }

    public static void main(String[] args) {

        List<TYPE> myList = new ArrayList<>();

        myList.add( TYPE.MEDIUM );

        // serialize
        String serializedJsonString = JsonbBuilder.create(new JsonbConfig().withLocale(Locale.GERMAN).withFormatting(true)).toJson(myList);

        // deserialize
        @SuppressWarnings("unchecked")
        List<TYPE> mySecondList = JsonbBuilder.create(new JsonbConfig().withLocale(Locale.GERMAN).withFormatting(true)).fromJson(serializedJsonString, List.class);

        System.out.println( myList.contains( TYPE.MEDIUM ) );       // will be true (as expected)

        System.out.println( mySecondList.contains( TYPE.MEDIUM ) ); // will be false (surprising!)
        System.out.println( mySecondList.contains( "MEDIUM" ) );    // will be true (surprising!)
    }
}

1 个答案:

答案 0 :(得分:0)

默认情况下,Java枚举被序列化为字符串,因为没有更好的默认JSON类型。 (您可以根据需要将它们配置为序列化为int。)

反序列化时,必须指示Jsonb解析器将JSON字符串转换为枚举,否则默认情况下会将其反序列化为Java字符串。

您在上面的示例中没有这样做,因为您要求它提供List.class(即List<?>),而不是TYPE枚举列表(List<TYPE> )。由于类型擦除,在Java中很难做到这一点。 (请注意,您必须将代码标记为“未经检查”,因为编译器知道您的版本将不起作用。)JsonB文档明确讨论了这种情况:http://json-b.net/docs/user-guide.html#mapping-a-generic-collection

尝试类似的东西:

List<TYPE> mySecondList = jsonb.fromJson(result, new ArrayList<TYPE>(){}.getClass().getGenericSuperclass());