Jak používat Rozhraní jako typ pole v Žádosti Tělo modelu třídy v rozhraní API Rest

0

Otázka

Máme Java SpringBoot API endpoint a míjíme RequestBody z NotifyMoiChanges typu třídy. V NotifyMoiChanges model třídy máme jednu podal což je typ Rozhraní.

Endpoint úryvek :

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

RequestBody Model úryvek:

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 je Rozhraní, které má dva implementace Type1MoiChangeValue & Type2MoiChangeValue.

Teď, když jsem se projít RequestBody založené na "operaci" podal data mám na mapě "hodnotu" pole Žádosti Těla s některou z Rozhraní implementace Type1MoiChangeValue nebo 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    ");
  }
}

Jsme pomocí jackson parser. Jak mohu dělat to. Prosím o radu!

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

Nejlepší odpověď

1

Budete potřebovat, aby se pár změn v kódu a v důsledku toho v žádosti těla. První je aktualizovat OneOfMoiChangeValue s pár Jackson anotací tak, že to může vědět, jak zacházet s různými podtypy na základě majetku jménem 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 {

}

To znamená, že již nepotřebujete operation ubytování v 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.
}

Místo toho musí být zaslány spolu se všemi ostatními vlastnostmi OneOfMoiChangeValue,, takže něco podél těchto linek:

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

Tohle vypadá dobře. Nech mě to zkusit a aktualizovat.
SuryaN

Ahoj @João , jen jsem teď přišel, že nemohu změnit žádost těla, a přidat další pole "operaci" uvnitř "hodnota" atribut jako Req Tělo je považován za standardní formát a nemáte oprávnění k manipulaci. Takže bez přidání jakékoli další pole v žádosti těla, můžeme to udělat?
SuryaN

Ne, že jsem si vědom. Jediná možnost by mohla být vlastní deserializer. Jsem opravdu rád, jak si lidé myslí, že software je sada do kamene věc a to, že změny nelze provést v žádném případě (vím, že to rozhodnutí není na tobě ;) ).
João Dias

Ano souhlasím s vámi. :) Musíme použít vlastní deserializer v tomto případě. Jsem nový na to. A tak se snaží psát nějaké, jestli to zvládnu.
SuryaN

Ahoj @João Dias, napsal jsem vlastní deserializer, jak jste řekl, a fungovalo to. Také návrh, který máte v odpovědi bude fungovat ve většině případů, neboť obecně se můžeme projít na další pole v json. Přijímám vaše řešení, jako to bylo správné. Díky za vaši pomoc k vyřešení :)
SuryaN

Jste vítáni! Zvažte také, že přidá své vlastní deserializer jako odpověď a přijmout to ;)
João Dias

V jiných jazycích

Tato stránka je v jiných jazycích

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