【问题标题】:Unable to get JsonIdentityInfo to work correctly无法让 JsonIdentityInfo 正常工作
【发布时间】:2020-10-16 02:17:36
【问题描述】:

我有两个对象之间的关系。我有一个 Spring CLI 与使用 Jackson 的 RESTful Web 服务进行通信。我正在使用 @JsonIdentityInfo 注释,但它无法在两个类之间创建关系。另外我正在使用 WebClient

第一个 Object 包含以下代码:

import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonSerialize(as= FuncUnit.class)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "fu_id", scope=FuncUnit.class)
@Setter @Getter 
public class FuncUnit  {

    @JsonProperty(value = "description")
    private String description;

    @Id @JsonProperty(value = "fu_id", required = true)
    private Long fu_id;

    // standard constructors    
    public FuncUnit (long fuId)
    {
        fu_id = fuId;
    }

    public FuncUnit() {}
}

第二个对象是:

@JsonSerialize(as=Engine.class)
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Engine.class)
@Setter @Getter 
public class Engine  {

    @JsonProperty(value = "id", required = true)
    private Long id;

    @JsonProperty(value = "func_unit")
    private FuncUnit func_unit;

    public Engine() {}
}

现在我收到的json如下:

[
    {
        "id": 111,
        "functional_unit": {
            "description": "",
            "fu_id": 11,
        },
    },
    {
        "id": 112,
        "functional_unit": 11,
    }
]

而我写的webClient代码如下。 (我也试过不使用 ExchangeStrategies,结果是一样的):

        ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
                .codecs(configurer ->
                        configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON)))
                .build();

        String url = cliUtils.getBaseUrl();
        WebClient webClient = WebClient.builder().exchangeStrategies(exchangeStrategies).build();
 
        UriComponentsBuilder builder = UriComponentsBuilder.newInstance().fromHttpUrl(url);

        List<Engine> units = webClient.get()
        .uri(builder.build().toUri())
        .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
        .retrieve()
        .bodyToFlux(Engine.class)
        .collectList()
        .block();

调用 webClient 代码时,我没有收到任何错误,但只有一个引擎具有 FuncUnit。 另一个引擎包含一个 null 作为 FuncUnit。

【问题讨论】:

    标签: java spring spring-boot jackson


    【解决方案1】:

    简短回答:改用 .bodyToMono(new ParameterizedTypeReference(){})。

    长答案: 我确实遇到了一些问题。经过大量研究,没有一个解决方案对我有用。比如 exchangeStrategy 上的自定义 ObjectMapper。

    我们知道 JsonIdentityInfo 将第一个实例序列化为完整对象,将其他相同对象序列化为引用,以防止循环引用问题。

    [
        {
            "id": 111,
            "functional_unit": {   // <----- First, Fully serialized
                "description": "",
                "fu_id": 11,
            },
        },
        {
            "id": 112,
            "functional_unit": 11,  // <----- Second, reference Id
        }
    ]
    

    但是,这个问题不是因为序列化/反序列化,而是因为 Flux 的行为。尽管我们使用flux.collectList() 来获取所有列表项,但它们实际上是一一返回(非阻塞)并收集所有。第二个和后面的相同项目将无法看到第一个引用并注入引用。所以我尝试使用 Mono> 来强制它们一起返回并且它起作用了。

    【讨论】:

      猜你喜欢
      • 2012-09-05
      • 2017-11-06
      • 2011-09-06
      • 1970-01-01
      • 2023-03-10
      • 2014-01-15
      • 2019-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多