【问题标题】:How to convert embedded JSON String inside JSON to java object?如何将 JSON 中嵌入的 JSON 字符串转换为 java 对象?
【发布时间】:2019-12-21 19:49:04
【问题描述】:

我有以下 json,其中 body 键包含一个值,它是 JSON 对象的字符串表示形式,我如何将其转换为 Java 对象?

我可以通过将 JSON 转换为 Map 来提取正文值,但我不知道应该如何从那里着手

input.json file

{
   "body": "{\n\t\"username\": \"TestUser\",\n\t\"password\": \"TestPassword\"\n}"
}

用户POJO如下,

class User {
   private String username;
   private String password;

   ... getters, setters and no-arg constructor
}

我的代码看起来是这样的,我需要实现convertToUser函数

public static void main(String[] args) {
    String jsonContent = readJsonFile("input.json");
    String escapedJsonBody = getBody(s);
    User user = convertToUser(escapedJsonBody, User.class);
}

我已经在使用 jackson java 库,非常感谢您对使用 jackson 进行此操作的任何见解。

【问题讨论】:

标签: java json jackson jackson-databind


【解决方案1】:

一种方法是创建 DTO 和转换器。拥有像这样的 DTO(我已经嵌套了类声明 jsut 以节省答案空间):

@Getter @Setter
public class Input { // this level maps to the whole input.json
    @JsonDeserialize(using =  BodyDeserializer.class) // custom deserializer below
    private Body body; // this is the body-attribute in JSON
    @Getter @Setter
    public static class Body {
        private User user;
        @Getter @Setter
        public static class User {
            private String username;
            private String password;
        }            
    }
}

转换器:

public class BodyDeserializer extends JsonDeserializer<Body> {
    private ObjectMapper om = new ObjectMapper(); // this is to read the user from string
    @Override
    public Body deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String embedded = p.readValueAs(String.class);
        Body body = new Body();
        body.setUser(om.readValue(embedded, User.class)); // here is the trick
        return body;
    }
}

像这样使用:

ObjectMapper om = new ObjectMapper();
String input = "{\"body\": \"{\\n\\t\\\"username\\\": \\\"TestUser\\\",\\n\\t\\\"password\\\": \\\"TestPassword\\\"\\n}\"}";
Input r = om.readValue(input, Input.class);

这种转换以通用方式发生的唯一缺点可能是您不喜欢创建 DTO 并像 Input.getBody().getUser(); 那样挖掘用户

【讨论】:

  • 得到以下错误,Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "username" (class eshop.common.lambdautil.Lambda$User), not marked as ignorable (0 known properties: ]) at [Source: (String)"{ "username": "TestUser", "password": "TestPassword" }"; line: 2, column: 15] (through reference chain: eshop.common.lambdautil.LambdaTest$Input["body"]-&gt;eshop.common.lambdautil.Lambda$User["username"]) at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
  • @vikkyhacks 你在运行我的代码时得到这个吗?如果没有,很难在没有看到反序列化代码的情况下判断出什么问题。这闻起来就像您正试图脱轨到不包含“用户名”的错误类。
  • 我试过这个确切的代码,发生的事情是,整个身体值被视为一个巨大的字符串。它试图找到与字符串{ "username": "TestUser", "password": "TestPassword" } 匹配的构造函数
  • @vikkyhacks 很奇怪,和我一起工作就像一个魅力。无论如何,我将反序列化器注释放在一个有点混乱的位置,将它移到字段上方,但不确定它是否重要,这两种方式都对我有用。我正在使用 jackson-databind,v 2.10.1。
  • 哦,让我再试一次
【解决方案2】:

要将 JSON 字符串转换为 java pojo,您可以使用 Jackson 的 ObjectMapper 类来帮助您完成此操作。

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.readValue(inputJson, User.class);

更多信息请访问 Jackson 的github page

【讨论】:

  • 这不适用于问题上的指定场景/
猜你喜欢
  • 2021-09-18
  • 2015-05-24
  • 2012-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
相关资源
最近更新 更多