jackson 如何将JSON反序列化为显式类

6yt4nkrj  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(135)

我有一个JSON,如下所示:

{
  "users": [{
      "name": "John"
  }]
}

我有一个类,我想在其中反序列化JSON:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "type",
        defaultImpl = User.class
)
@JsonSubTypes({
        @JsonSubTypes.Type(name = "myUser", value = MyUser.class),
        @JsonSubTypes.Type(name = "guestUser", value = GuestUser.class)
})
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
  public String name;
}

public class MyUser extends User {
  ...
}

public class Request {
  List<MyUser> users;  // I can't change List<MyUser> to List<User>
}

当我尝试用下一种方法反序列化它时

public static void main(String[] args) {
    ObjectMapper mapper = new ObjectMapper();
    Request request = mapper.readValue(json, Request.class);
    System.out.println(request);
}

我得到了一个异常:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when trying to resolve subtype of [simple type, class com.example.MyUser]: missing type id property 'type' (for POJO property 'users')

我不明白为什么我会得到这个异常...我定义了一个显式类MyUser。有人能帮我避免这个异常吗?

7gyucuyw

7gyucuyw1#

我建议使用Jackson Mixin特性。该特性允许在类本身的源代码之外从外部添加和修改类的注解。
在本例中,您希望反序列化用户列表,并告诉jackson忽略在User中指定的类型信息。
第一步是用@JsonTypeInfo创建一个类,它显式地定义要使用的impl。我们可以使用接口,因为它从来没有示例化过。它只是用来保存注解

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NONE,  // use no property as type info
    defaultImpl = MyUser.class   // use this impl as deserialization target 
)
public interface UserMixin {
}

接下来我们在创建Map器时将mixin绑定到User类:

ObjectMapper mapper = new ObjectMapper()
        .addMixIn(User.class, UserMixin.class);

这告诉jackson到使用任何注解从这mixin当反序列化进User对象.在两个相同注解的情况下,这mixin将是使用. overriding注解从目标类.
试验方法

public static void main(String[] args) {
    String json = """
        {
            "users": [{
                "name": "John"
            }]
        }
         """;
    try {
        ObjectMapper mapper = new ObjectMapper()
            .addMixIn(User.class, UserMixin.class);
        Request request = mapper.readValue(json, Request.class);
        System.out.println(request.users.get(0).name);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出符合预期...

相关问题