java - 如何使用 Jackson ObjectMapper 反序列化 Spring 的 ResponseEntity (可能使用 @JsonCreator 和 Jackson mixins)

标签 java spring jackson deserialization mixins

ResponseEntity doesn't have a default constructor 。 然后,为了使用 objectMapper 反序列化它,我决定使用 araqnid 在 that answer 中给出的方法。 。 很快 - 它需要使用 Jackson 的 mixin 功能以及 @JsonCreator。

就我而言(使用 ResponseEntity),由于不同的原因,它尚未解决。

我的测试方法如下:

public static void main(String[] args) throws Exception {
    ResponseEntity<Object> build = ResponseEntity.ok().build();

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.addMixIn(ResponseEntity.class, ResponseEntityMixin.class);

    String s = objectMapper.writeValueAsString(build);
    ResponseEntity<Object> result = objectMapper.readValue(s, ResponseEntity.class);

    System.out.println(result);
}

首先,我尝试使用最短的 mixin 构造函数:

public abstract static class ResponseEntityMixin {
    @JsonCreator
    public ResponseEntityMixin(@JsonProperty("status") HttpStatus status) {
    }
}

在这种情况下,我收到一个断言错误,因为 ResponseEntity 在其构造函数中包含这行代码:

Assert.notNull(status, "HttpStatus must not be null");

然后我将 @JsonCreator 的模式切换为 DELEGATING 但在这种情况下我遇到了另一个异常:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `org.springframework.http.HttpStatus` from String "headers": value not one of declared Enum instance names: [UPGRADE_REQUIRED, UNAVAILABLE_FOR_LEGAL_REASONS, SERVICE_UNAVAILABLE, CHECKPOINT, LOCKED, METHOD_FAILURE, FAILED_DEPENDENCY, UNPROCESSABLE_ENTITY, PROCESSING, PROXY_AUTHENTICATION_REQUIRED, METHOD_NOT_ALLOWED, GONE, MULTIPLE_CHOICES, GATEWAY_TIMEOUT, ACCEPTED, TEMPORARY_REDIRECT, INTERNAL_SERVER_ERROR, URI_TOO_LONG, LOOP_DETECTED, PAYLOAD_TOO_LARGE, EXPECTATION_FAILED, MOVED_TEMPORARILY, REQUEST_ENTITY_TOO_LARGE, NOT_EXTENDED, CREATED, RESET_CONTENT, BAD_GATEWAY, CONFLICT, VARIANT_ALSO_NEGOTIATES, NETWORK_AUTHENTICATION_REQUIRED, NOT_FOUND, LENGTH_REQUIRED, INSUFFICIENT_SPACE_ON_RESOURCE, NO_CONTENT, OK, FOUND, SEE_OTHER, BANDWIDTH_LIMIT_EXCEEDED, REQUEST_HEADER_FIELDS_TOO_LARGE, PERMANENT_REDIRECT, NOT_ACCEPTABLE, MOVED_PERMANENTLY, REQUEST_TIMEOUT, UNAUTHORIZED, USE_PROXY, IM_USED, ALREADY_REPORTED, PARTIAL_CONTENT, PRECONDITION_FAILED, REQUEST_URI_TOO_LONG, BAD_REQUEST, INSUFFICIENT_STORAGE, CONTINUE, NON_AUTHORITATIVE_INFORMATION, REQUESTED_RANGE_NOT_SATISFIABLE, UNSUPPORTED_MEDIA_TYPE, I_AM_A_TEAPOT, HTTP_VERSION_NOT_SUPPORTED, SWITCHING_PROTOCOLS, NOT_MODIFIED, NOT_IMPLEMENTED, TOO_MANY_REQUESTS, DESTINATION_LOCKED, PAYMENT_REQUIRED, FORBIDDEN, PRECONDITION_REQUIRED, MULTI_STATUS]
 at [Source: (String)"{"headers":{},"body":null,"statusCode":"OK","statusCodeValue":200}"; line: 1, column: 2]

我还尝试使用 ResponseEntity 的全参数构造函数,但由于 MultiValueMap 反序列化问题,它也没有成功(但我相信,如果我修复它,那么它最终会让我遇到与上述相同的问题)。

谁能帮我解决这个问题吗?也许在这种情况下根本不可能使用 mixins ?

如果您知道如何使用 Jackson 反序列化 ResponseEntity 的另一种方法 - 请也提供它们。

这是我测试的源代码:https://github.com/amseager/responseentitydeserialization

最佳答案

使用MixIns是解决这个问题的好方法:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

public class Main {
    public static void main(String[] args) throws Exception {
        ResponseEntity<Object> entity = ResponseEntity
                .ok()
                .header("header", "value")
                .body("Everything is OK!");

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.addMixIn(ResponseEntity.class, ResponseEntityMixin.class);
        objectMapper.addMixIn(HttpStatus.class, HttpStatusMixIn.class);

        String json = objectMapper.writeValueAsString(entity);
        TypeReference ref = new TypeReference<ResponseEntity<Object>>() {
        };
        ResponseEntity<Object> result = objectMapper.readValue(json, ref);
        System.out.println(result);
        System.out.println(result.equals(entity));
    }
}

@JsonIgnoreProperties(ignoreUnknown = true)
class ResponseEntityMixin {
    @JsonCreator
    public ResponseEntityMixin(@JsonProperty("body") Object body,
                               @JsonDeserialize(as = LinkedMultiValueMap.class) @JsonProperty("headers") MultiValueMap<String, String> headers,
                               @JsonProperty("statusCodeValue") HttpStatus status) {
    }
}

class HttpStatusMixIn {

    @JsonCreator
    public static HttpStatus resolve(int statusCode) {
        return HttpStatus.NO_CONTENT;
    }
}

上面的代码打印:

<200 OK OK,Everything is OK!,[header:"value"]>


true 表示源对象和反序列化对象相同。

关于java - 如何使用 Jackson ObjectMapper 反序列化 Spring 的 ResponseEntity (可能使用 @JsonCreator 和 Jackson mixins),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58982242/

相关文章:

java - 如何即时修改 java 属性?

java - 为什么 HashMap 重新散列键对象提供的散列码?

java - 以标准化方式将对象传递给接口(interface)/抽象类

java - Spring Rest 应用程序未启动(NullPointerException)

java - Spring 启动。即使数据库中有对象,GET 方法为什么返回 null?

android - 使用 Kotlin 默认值的 Jackson 反序列化失败

java - 复制文件而不创建 FileOutputStream

java - NetBeans 7.2,启动maven spring项目并添加hibernate

java - 如何在Spring上获取没有关系的序列化对象

java - Jackson 如何使用自定义 getter/setter 序列化 map ?