RestTemplate 发送 Post 请求并处理响应(JSON)在 Spring Boot 中

huangapple go评论65阅读模式
英文:

RestTemplate Post and response ( JSON ) Spring boot

问题

我使用restTemplate实现一个帖子,带有表示json字段的对象,并希望答案是一个表示答案本身的object对象。

例如,json如下:

{
    "content": {
        "name": "support-callmebackmodals-view_web",
        "data": {
            "channel": "web",
            "productName": "book"
        }
    }
}

表示它的类如下:

@Getter
@Setter
@NoArgsConstructor
public class Request {
    Con ContentObject;
}

ConClass包含json的“content”,content包含name和DataClass等。

我创建的翻译为对象的响应是:

@Getter
@Setter
@NoArgsConstructor
@ToString
public class AssistenzaResponse {
    
    private boolean success;
    private String error;
    Results results;
}

@Getter
@Setter
@NoArgsConstructor
public class Results {

    Content content;
}

@Getter
@Setter
@NoArgsConstructor
public class Content {
    Meta meta;
    private String name;
    private String html;
    private float duration;
    private float statusCode;
    private boolean success;
    private String error;
}

@Getter
@Setter
@NoArgsConstructor
public class Meta {
    private String src;
}

我的service如下:

@Service
public class AssistenzaService {
    public AssistenzaResponse getUno() throws IOException {

        String url = "https://support.aasdt/batch";

        org.apache.http.client.HttpClient client = HttpClientBuilder.create().build();

        Request request1 = new Request();
        Con con = new Con();
        con.setName("support-callmebackmodals-view_web");

        Data data = new Data();
        data.setChannel("web");
        data.setProductName("LibrettoMinori");
        con.setData(data);
        RestTemplate restTemplate = new RestTemplate();
        request1.setContentObject(con);
        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");
        headers.set("Accept", "application/json");
        HttpEntity<Request> entity = new HttpEntity<>(request1, headers);

        try {
            ResponseEntity<AssistenzaResponse> response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);

            return response.getBody();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
}

但答案不是我期望的,因为它返回:

{
    "success": true,
    "error": null,
    "results": {
        "results": null
    }
}

但如果我使用:

ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

响应是正确的,如下:

{
    "success": true,
    "error": null,
    "results": {
        "content": {
            "name": "support-callmebackmodals-view_web",
            "html": "",
            "meta": {
                "src": "/support/client.js"
            },
            "duration": 7.694401,
            "statusCode": 200,
            "success": true,
            "error": null
        }
    }
}

为什么我不使用我创建的答案对象获得准确的答案?

但如果我使用字符串,它可以工作?

我期望json答案不以String形式返回,而是以我的Response对象返回,我尝试使用postForObjectpostForEntity也是如此。

英文:

I am implementing a post with restTemplate, with body an object representing a fields of a json and I would like the answer with an object representing the json fields of the answer itself.

For example, the json is this:

{
    &quot;content&quot;: {
        &quot;name&quot;: &quot;support-callmebackmodals-view_web&quot;,
        &quot;data&quot;: {
            &quot;channel&quot;: &quot;web&quot;,
            &quot;productName&quot;: &quot;book&quot;
        }
    }
}

The class that represents it is this:

@Getter
@Setter
@NoArgsConstructor
public class Request {
    Con ContentObject;
}

ConClass contains "content" of json, content contains name and DataClass ecc.

The response translated into object I created is:

@Getter
@Setter
@NoArgsConstructor
@ToString
public class AssistenzaResponse {
    
    private boolean success;
    private String error;
    Results results;
}

@Getter
@Setter
@NoArgsConstructor
public class Results {

    Content content;
}

@Getter
@Setter
@NoArgsConstructor
public class Content {
    Meta meta;
    private String name;
    private String html;
    private float duration;
    private float statusCode;
    private boolean success;
    private String error;
}

@Getter
@Setter
@NoArgsConstructor
public class Meta {
    private String src;
}

My service is this:

@Service
public class AssistenzaService {
    public AssistenzaResponse getUno() throws IOException {

        String url = &quot;https://support.aasdt/batch&quot;;


        org.apache.http.client.HttpClient client = HttpClientBuilder.create().build();

        Request request1 = new Request();
        Con con = new Con();
        con.setName(&quot;support-callmebackmodals-view_web&quot;);

        Data data = new Data();
        data.setChannel(&quot;web&quot;);
        data.setProductName(&quot;LibrettoMinori&quot;);
        con.setData(data);
        RestTemplate restTemplate = new RestTemplate();
        request1.setContentObject(con);
        HttpHeaders headers = new HttpHeaders();
        headers.set(&quot;Content-Type&quot;, &quot;application/json&quot;);
        headers.set(&quot;Accept&quot;, &quot;application/json&quot;);
        HttpEntity&lt;Request&gt; entity = new HttpEntity&lt;&gt;(request1, headers);

        try {
            ResponseEntity&lt;AssistenzaResponse&gt; response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);

            return response.getBody();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return null;
    }
}

But the answer is not what I expect, because it returns:

{
    &quot;success&quot;: true,
    &quot;error&quot;: null,
    &quot;results&quot;: {
        &quot;results&quot;: null
    }
}

Instead if I use:

ResponseEntity&lt;String&gt; response = restTemplate.exchange(url,HttpMethod.POST, entity, String.class);         

The response is correct and it is:

{
    &quot;success&quot;: true,
    &quot;error&quot;: null,
    &quot;results&quot;: {
        &quot;content&quot;: {
            &quot;name&quot;: &quot;support-callmebackmodals-view_web&quot;,
            &quot;html&quot;: &quot;&quot;,
            &quot;meta&quot;: {
                &quot;src&quot;: &quot;/support/client.js&quot;
            },
            &quot;duration&quot;: 7.694401,
            &quot;statusCode&quot;: 200,
            &quot;success&quot;: true,
            &quot;error&quot;: null
        }
    }
}

Why don't I get the exact answer using the answer object I created?

But if I use the string it works?

I expect that the json answer will not be returned as String, but as my Response object, I tried to use also postForObject and postForEntity.

答案1

得分: 1

问题在于您收到的JSON响应的结构与您用于反序列化的AssistenzaResponse类的结构不匹配。因此,RestTemplate无法正确地将JSON响应转换为AssistenzaResponse对象。

您可以通过更改AssistenzaResponse类以匹配您收到的JSON响应的结构来解决此问题。在您的情况下,您需要向AssistenzaResponse类添加一层嵌套。可以这样做,例如:

@Getter
@Setter
@NoArgsConstructor
public class AssistenzaResponse {
    private boolean success;
    private String error;
    private Results results;

    @Getter
    @Setter
    @NoArgsConstructor
    public static class Results {
        private Content content;

        @Getter
        @Setter
        @NoArgsConstructor
        public static class Content {
            private String name;
            private String html;
            private Meta meta;
            private float duration;
            private float statusCode;
            private boolean success;
            private String error;

            @Getter
            @Setter
            @NoArgsConstructor
            public static class Meta {
                private String src;
            }
        }
    }
}

然后,您可以在调用RestTemplate.exchange()时使用AssistenzaResponse而不是String,就像您以前所做的那样:

ResponseEntity<AssistenzaResponse> response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);
return response.getBody();

现在,RestTemplate应该能够正确地将JSON响应转换为AssistenzaResponse对象。试试看吧!

英文:

The problem is that the structure of the JSON response you are receiving does not match the structure of the AssistenzaResponse class you are using for deserialization. Therefore, RestTemplate cannot correctly convert the JSON response into an AssistenzaResponse object.

You can fix this by changing the AssistenzaResponse class to match the structure of the JSON response you are receiving. In your case, you need to add one more level of nesting to the AssistenzaResponse class. This can be done, for example, as follows:

@Getter
@Setter
@NoArgsConstructor
public class AssistenzaResponse {
    private boolean success;
    private String error;
    private Results results;

    @Getter
    @Setter
    @NoArgsConstructor
    public static class Results {
        private Content content;

        @Getter
        @Setter
        @NoArgsConstructor
        public static class Content {
            private String name;
            private String html;
            private Meta meta;
            private float duration;
            private float statusCode;
            private boolean success;
            private String error;

            @Getter
            @Setter
            @NoArgsConstructor
            public static class Meta {
                private String src;
            }
        }
    }
}

You can then use AssistenzaResponse instead of String when calling RestTemplate.exchange() like you did before:

ResponseEntity&lt;AssistenzaResponse&gt; response = restTemplate.exchange(url, HttpMethod.POST, entity, AssistenzaResponse.class);
return response.getBody();

The RestTemplate should now properly convert the JSON response into an AssistenzaResponse object. Try it!

huangapple
  • 本文由 发表于 2023年2月23日 19:34:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定