【问题标题】:Map JSON leaf to an object via RestTemplate postForObject通过 RestTemplate postForObject 将 JSON 叶映射到对象
【发布时间】:2014-08-05 05:51:05
【问题描述】:

使用返回 json 字符串的 restful api。格式为

{
  "status": "ok",
  "result": { <the method result> }
}

我正在尝试将用户配置文件的响应映射到 UserProfile.class

MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("method", "currentUser");
URI url = buildUri("users/show.json");
UserProfile profile = this.getRestTemplate().postForObject(url, parameters, UserProfile.class );

用户配置文件包含响应结果中的所有字段。如果我添加字段字符串状态、UserProfile 结果,它会将 UserProfile 映射到结果,我可以从那里提取它,但感觉有点不对。

我希望 postForObject 函数将 JSON 响应相关的叶子“结果”映射到 UserProfile.class

【问题讨论】:

    标签: java json spring rest jackson


    【解决方案1】:

    对我来说,最清晰的方法是将响应结果映射到包含用户配置文件对象的对象。您将避免进行自定义反序列化的不必要的复杂化,并允许您访问状态代码。您甚至可以将响应结果对象设为通用,以便它适用于任何类型的内容。

    这是一个使用 Jackon 的对象映射器的示例。在 Spring 中,您需要使用ParameterizedTypeReference 来传递泛型类型信息(请参阅this answer):

    public class JacksonUnwrapped {
    
        private final static String JSON = "{\n" +
                "  \"status\": \"ok\",\n" +
                "  \"result\": { \"field1\":\"value\", \"field2\":123 }\n" +
                "}";
    
    
        public static class Result<T> {
            public final String status;
            public final T result;
    
            @JsonCreator
            public Result(@JsonProperty("status") String status,
                          @JsonProperty("result") T result) {
                this.status = status;
                this.result = result;
            }
    
            @Override
            public String toString() {
                return "Result{" +
                        "status='" + status + '\'' +
                        ", result=" + result +
                        '}';
            }
        }
    
        public static class UserProfile {
            public final String field1;
            public final int field2;
    
            @JsonCreator
            public UserProfile(@JsonProperty("field1") String field1,
                               @JsonProperty("field2") int field2) {
                this.field1 = field1;
                this.field2 = field2;
            }
    
            @Override
            public String toString() {
                return "UserProfile{" +
                        "field1='" + field1 + '\'' +
                        ", field2=" + field2 +
                        '}';
            }
        }
    
        public static void main(String[] args) throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            Result<UserProfile> value = mapper.readValue(JSON, new TypeReference<Result<UserProfile>>() {});
            System.out.println(value.result);
        }
    
    }
    

    输出:

    UserProfile{field1='value', field2=123}
    

    【讨论】:

    • 如何使用 Result 中的 getter 方法获取用户?我想出了类似的东西。困扰我的事情是,为了获取其他类型的对象,比如说 UserSettings,我必须有另一个 Result(如 UserSettingsResult)类,只是参数中的类型不同......这适用于每个 postForObject() 方法。看起来代码重复太多,无法适应每种类型。
    • 您可以使结果对象通用,以便它可以容纳任何类型的内容对象。我已经更新了我的答案以展示如何做到这一点。
    • 成功了!我将它调整为我自己的版本,没有嵌套类,但 ParameterizedTypeReference 使它工作!只是提醒任何这样做的人,Intellij 在逐步调试评估时会为您提供错误,因为它无法分析匿名类。只需按 f8 即可查看结果。
    猜你喜欢
    • 2018-05-16
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 2019-07-22
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多