Jak korzystać z Inteface jako typ pola w klasie modelu ciała zapytania w Rest API

0

Pytanie

Mamy punkt końcowy API Java SpringBoot, i przekazujemy treść żądania typu klasy NotifyMoiChanges. W klasie modelu NotifyMoiChanges mamy jeden plik, który jest typem interfejsu.

Fragment punktu końcowego :

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

Fragment modelu ciała zapytania:

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-jest to interfejs, który ma dwie realizacji Type1MoiChangeValue i Type2MoiChangeValue.

Teraz, kiedy przekazuję treść żądania na podstawie danych podanych w "operacji", muszę dopasować pole "wartość" ciała żądania od każdego z implementacji interfejsu Type1MoiChangeValue lub Type2MoiChangeValue.

public interface OneOfMoiChangeValue {

}

Wartość 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    ");
  }
}

Wartość typu 2moichangevalue:

@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    ");
  }
}

Używamy parser Jacksona. Jak mogę to zrobić. Proszę skonsultować się!

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

Najlepsza odpowiedź

1

Trzeba będzie wprowadzić kilka zmian do swojego kodu i, w konsekwencji, w ciało swojego zapytania. Po pierwsze, należy zaktualizować OneOfMoiChangeValue z kilku komentarzy Jacksona, aby mógł wiedzieć, jak obsługiwać różne podtypy na podstawie właściwości o nazwie 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 {

}

Oznacza to, że nie są już potrzebne operation nieruchomości w 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.
}

Zamiast tego powinien być wysłany razem ze wszystkimi innymi właściwościami OneOfMoiChangeValuetak , że coś w następujących wierszy:

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

To wygląda dobrze. Pozwól mi spróbować i poinformować.
SuryaN

Cześć @João , ja dopiero teraz się dowiedziałem, że nie mogę zmienić treść żądania i dodać dodatkowe pole "operacja" wewnątrz atrybutu "wartość", ponieważ ciało zapytania jest standardowym formatem i nie ma zgody na to manipulacja. Tak więc, czy możemy to zrobić, nie dodając żadnych dodatkowych pól w ciało zapytania?
SuryaN

O ile mi wiadomo, nie ma. Jedynym rozwiązaniem może być niestandardowy десериализатор. Bardzo podoba mi się to, jak ludzie myślą, że oprogramowanie-to jest rzecz, wykuta w skale, i że zmiany w żaden sposób nie mogą być wprowadzone (wiem, że to nie twoja decyzja ;) ).
João Dias

Tak, zgadzam się z tobą. :) W tym przypadku musimy użyć niestandardowego десериализатор. Jestem w tym początkujący. Więc staram się napisać coś, jeśli będę w stanie to zrobić.
SuryaN

Cześć @João Dias, napisałem własny десериализатор, jak pan powiedział, i zadziałał. Również oferta, którą masz w odpowiedzi, będzie działać w większości przypadków, tak jak zwykle możemy przekazać dodatkowe pole w formacie json. Akceptuję twoją decyzję tak, jak to było słuszne. Dziękuję za pomoc w jej rozwiązaniu :)
SuryaN

Witamy! Pomyśl również o dodaniu użytkownika десериализатора jako odpowiedzi i zapoznać go ;)
João Dias

W innych językach

Ta strona jest w innych językach

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