Como usar a Interface como um tipo de campo no Corpo do Pedido de modelo de classes na API Rest

0

Pergunta

Temos um Java SpringBoot API de ponto de extremidade e nós passamos um RequestBody de NotifyMoiChanges tipo de classe. Em NotifyMoiChanges classe de modelo, temos um arquivados que é tipo de Interface.

Ponto de extremidade do trecho :

@PostMapping("/notifyMOIChanges")
public ResponseEntity<Void> notifyMOIChangesPost(@RequestBody NotifyMoiChanges notifyMoiChanges) {
        logger.info("Received notifyMOIChanges request.");
        return ResponseEntity.noContent().build();
    }

RequestBody Modelo trecho:

public class NotifyMoiChanges {
  @JsonProperty("moiChanges")
  @Valid
  private List<MoiChange> moiChanges = new ArrayList<MoiChange>();
  ..... other attributes
}

public class MoiChange   {
      @JsonProperty("operation")
      private String operation = null;   //operation value can be "Type1" or "Type2"
    
      @JsonProperty("value")
      private OneOfMoiChangeValue value = null;   //value filed can be mapped with any of the OneOfMoiChangeValue Interface implentations  Type1MoiChangeValue or Type2MoiChangeValue.
    }

OneOfMoiChangeValue é uma Interface que tem duas implementações Type1MoiChangeValue & Type2MoiChangeValue.

Agora quando eu passo um RequestBody com base na "operação", apresentado dados que eu tenho para mapear o 'valor' campo de Solicitação de Corpo com qualquer uma das implementações de Interface Type1MoiChangeValue ou Type2MoiChangeValue.

public interface OneOfMoiChangeValue {

}

Type1MoiChangeValue:

@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2021-11-16T11:51:46.436+05:30[Asia/Calcutta]")
public class Type1MoiChangeValue  extends ArrayList<Type2MoiChangeValue > implements OneOfMoiChangeValue {

  @Override
  public boolean equals(java.lang.Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(super.hashCode());
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class Type1MoiChangeValue {\n");
    sb.append("    ").append(toIndentedString(super.toString())).append("\n");
    sb.append("}");
    return sb.toString();
  }

  /**
   * Convert the given object to string with each line indented by 4 spaces
   * (except the first line).
   */
  private String toIndentedString(java.lang.Object o) {
    if (o == null) {
      return "null";
    }
    return o.toString().replace("\n", "\n    ");
  }
}

Type2MoiChangeValue:

@javax.annotation.Generated(value = "io.swagger.codegen.v3.generators.java.SpringCodegen", date = "2021-11-16T11:51:46.436+05:30[Asia/Calcutta]")
public class Type2MoiChangeValue extends HashMap<String, Object> implements OneOfMoiChangeValue {

  @Override
  public boolean equals(java.lang.Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(super.hashCode());
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("class Type2MoiChangeValue {\n");
    sb.append("    ").append(toIndentedString(super.toString())).append("\n");
    sb.append("}");
    return sb.toString();
  }

  /**
   * Convert the given object to string with each line indented by 4 spaces
   * (except the first line).
   */
  private String toIndentedString(java.lang.Object o) {
    if (o == null) {
      return "null";
    }
    return o.toString().replace("\n", "\n    ");
  }
}

Estamos usando jackson analisador. Como posso fazê-lo. Por favor, conselhos!

interface jackson java spring
2021-11-23 07:51:37
1

Melhor resposta

1

Você vai precisar de um par de alterações em seu código e, como consequência, em seu pedido de corpo. A primeira é para atualização de OneOfMoiChangeValue com um par de Jackson anotações para que ele possa saber como lidar com os diferentes subtipos com base em uma propriedade denominada operation:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import static com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME;

@JsonTypeInfo(use = NAME, include = PROPERTY, property = "operation")
@JsonSubTypes({
  @JsonSubTypes.Type(value=Type1MoiChangeValue.class, name = "Type1"),
  @JsonSubTypes.Type(value=Type2MoiChangeValue.class, name = "Type2")
})
public interface OneOfMoiChangeValue {

}

Isso significa que você não precisa mais do operation propriedade MoiChange:

public class MoiChange {
      @JsonProperty("value")
      private OneOfMoiChangeValue value = null;   //value filed can be mapped with any of the OneOfMoiChangeValue Interface implentations  Type1MoiChangeValue or Type2MoiChangeValue.
}

Em vez disso, ele deve ser enviado juntamente com todas as outras propriedades de OneOfMoiChangeValue, então, algo ao longo das seguintes linhas:

{
    "moiChanges": 
    [
        {
            "value": {
                "operation": "Type1",
                (...)
            }    
        },
        {
            "value": {
                "operation": "Type2",
                (...)
            }    
        },
        (...)
    ]
}
2021-11-23 14:56:57

Isso parece ser bom. Deixe-me experimentá-lo e atualizá-lo.
SuryaN

Oi @João , eu só agora vim a saber que não posso mudar o corpo do pedido e adicionar extra campo "operação" dentro do 'valor' atributo como o Req Corpo é considerado como formato padrão e não tem permissão para manipulá-lo. Assim, sem a adição de qualquer campo extra no corpo do pedido podemos fazer isso?
SuryaN

Não que eu estou ciente. A única opção poderia ser uma custom desserializador. Eu realmente gosto de como as pessoas pensam que o software é um conjunto em pedra coisa e que as alterações não podem ser feitas em qualquer forma (eu sei que isso não é uma decisão sua ;) ).
João Dias

Sim concordo com você. :) Temos que usar personalizado desserializador neste caso. Eu sou novo para isso. De modo a tentar escrever algumas se eu posso fazer isso.
SuryaN

Oi @João Dias, eu escrevi um personalizado desserializador como você disse e funcionou. Também a sugestão de que você tem a resposta vai funcionar na maioria dos casos, como podemos geralmente passar o extra-campo em json. Eu estou aceitando sua solução: como ela estava correta. Obrigado por sua ajuda para resolvê-lo :)
SuryaN

Você é bem-vindo! Considere também a possibilidade de adicionar o seu personalizado desserializador como uma resposta e aceitá-lo ;)
João Dias

Em outros idiomas

Esta página está em outros idiomas

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................