Come utilizzare l'Interfaccia come un tipo di campo nel Corpo di Richiesta modello di classe in Rest API

0

Domanda

Abbiamo un Java SpringBoot endpoint API e passiamo una RequestBody di NotifyMoiChanges tipo di classe. In NotifyMoiChanges modello di classe in più abbiamo uno depositata, che è il tipo di Interfaccia.

Endpoint snippet :

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

RequestBody Modello snippet:

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 è un'Interfaccia che ha due implementazioni Type1MoiChangeValue & Type2MoiChangeValue.

Ora, quando mi passa un RequestBody basato sul 'funzionamento' presentato dati che ho la mappa di campo "valore" della Richiesta del Corpo con una qualsiasi delle implementazioni di Interfaccia Type1MoiChangeValue o 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    ");
  }
}

Stiamo usando jackson parser. Come posso fare. Si prega di consigli!

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

Migliore risposta

1

Avrete bisogno di un paio di modifiche nel codice e, come conseguenza, nel corpo della richiesta. Il primo è quello di aggiornare OneOfMoiChangeValue con un paio di Jackson annotazioni, in modo che si può sapere come gestire i diversi sottotipi in base a una proprietà di nome 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 {

}

Questo significa che non è più necessario il operation proprietà in 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.
}

Invece, deve essere inviato insieme a tutte le altre proprietà di OneOfMoiChangeValuequindi qualcosa lungo le seguenti linee:

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

Questo sembra buono. Fammi provare e si aggiorna.
SuryaN

Ciao @João , io solo ora sono venuto a sapere che non posso cambiare il corpo della richiesta e aggiungere il campo 'operazione' all'interno del 'valore' attributo come Req Corpo è considerato come formato standard e non hai il permesso di manipolare. Così, senza aggiunta di extra campo nel corpo della richiesta siamo in grado di farlo?
SuryaN

Non che io sappia. L'unica opzione potrebbe essere una custom deserializer. Mi piace molto come la gente pensa che è un software per impostare in pietra, che cosa e che le modifiche non possono essere fatte in qualsiasi modo (so che non è questa la tua decisione ;) ).
João Dias

Sì d'accordo con te. :) Dobbiamo usare personalizzato deserializer in questo caso. Io sono di nuovo ad esso. Così cercando di scrivere un po ' se riesco a farlo.
SuryaN

Ciao @João Dias, ho scritto un custom deserializer come hai detto e ha funzionato. Anche il suggerimento è di avere la risposta che funzionano nella maggior parte dei casi, come in generale si può passare il campo aggiuntivo in json. Sto accettando la soluzione, come è stato corretto. Grazie per il vostro aiuto a risolverlo :)
SuryaN

Sei il benvenuto! Considera anche l'aggiunta personalizzati deserializer come una risposta e di accettarlo ;)
João Dias

In altre lingue

Questa pagina è in altre lingue

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