Cum să utilizați Inteface ca un tip de câmp în Organism Cerere model de clasa in Rest API

0

Problema

Avem un Java SpringBoot API final și vom trece un RequestBody de NotifyMoiChanges de tip clasă. În NotifyMoiChanges model de clasa avem un singur depus care este tipul de Interfață.

Endpoint fragment :

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

RequestBody Model fragment:

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 este o Interfață care are două implementări Type1MoiChangeValue & Type2MoiChangeValue.

Acum, când trec pe lângă o RequestBody bazat pe "operațiune" depus de date trebuie să hartă "valoarea" domeniul de Solicitare a Organismului cu oricare dintre implementările de Interfață Type1MoiChangeValue sau 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    ");
  }
}

Suntem folosind jackson parser. Cum pot face asta. Va rog un sfat!

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

Cel mai bun răspuns

1

Veți avea nevoie de câteva modificări în cod și ca o consecință, în corpul cerere. Primul este de a actualiza OneOfMoiChangeValue cu o pereche de Jackson adnotări astfel încât să poată ști cum să se ocupe de diferite subtipuri bazează pe o proprietate numită 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 {

}

Acest lucru înseamnă că nu mai aveți nevoie de operation de proprietate în 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.
}

În schimb, acesta trebuie să fie trimis, alături de toate celelalte proprietăți ale OneOfMoiChangeValue, deci ceva de-a lungul următoarele linii:

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

Asta arata bine. Lasă-mă să încerc și actualizare.
SuryaN

Salut @Joao , am venit acum să știi că nu se poate schimba la cerere, corpul și se adaugă câmp suplimentar "operațiune" în interiorul "valoare" atribut ca Req Corpul este considerat ca fiind format standard și nu aveți permisiunea să-l manipuleze. Deci, fără să adăugați orice câmp suplimentar în organism cerere putem face?
SuryaN

Nu că sunt conștienți de. Singura opțiune ar putea fi un obicei deserializer. Îmi place foarte mult cum cred oamenii că software-ul este un set in stone lucru și că schimbările nu pot fi făcute în orice fel (stiu ca asta nu e decizia ta ;) ).
João Dias

Da sunt de acord cu tine. :) Avem de a utiliza personalizat deserializer în acest caz. Eu sunt nou la ea. Așa că încearcă să scrie ceva dacă eu pot face asta.
SuryaN

Salut @Joao Dias, am scris un obicei deserializer cum ai zis si a mers. De asemenea, sugestia aveți în răspunsul va lucra în cele mai multe cazuri ca putem, în general, trece câmp suplimentar în json. Am acceptat solutia ta ca a fost corect. Vă mulțumim pentru ajutorul tău pentru a rezolva :)
SuryaN

Sunteți bineveniți! Ia în considerare, de asemenea, adăugarea de personalizat deserializer ca un răspuns și să-l accepte ;)
João Dias

În alte limbi

Această pagină este în alte limbi

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