Definice problému
Mám Spring Boot aplikaci REST JSON služby. Služba má definované API pomocí YAML. Z YAML souboru jsou generovány Java třídy pomocí openapi-generator-maven-plugin verze 6.6.0 nebo novější.
Pokud je v YAML
oneOf:
- $ref: '#/components/schemas/AddresseeBranch'
- $ref: '#/components/schemas/AddresseeHome'
Je při generování vytvořeno rozhraní Addressee a třídy AddresseeBranch a AddresseeHome implementující rozhraní Addressee.
Při volání služby a následném pokusu o deserializaci nastane chyba
Cannot construct instance of `...Akddressee` (no Creators, like default constructor, exist).
Ta je způsobena tím, že deserializer neví na kterou instanci mapovat. Použije proto (nevhodně) samotné rozhraní, které však nelze instanciovat.
Tento problém je na githubu ve stavu otevřený.
Řešení
V některých případech (kdy je jedna z implementací pouhým rozšířením druhé) je možné pomocí SimpleAbstractTypeResolver napevno definovat na kterou z uvedených instancí se mají příchozí data deserializovat. Takové řešení je popsáno zde.
Obecné řešení však spočívá v použití diskriminátoru v YAML definici:
oneOf:
- $ref: '#/components/schemas/AddresseeBranch'
- $ref: '#/components/schemas/AddresseeHome'
discriminator:
propertyName: objectType
Následně je třeba v každém z referencovaných objektů definovat property objectType typu String. Ta by měla mít hodnotu odpovídající názvu reference (tj. názvu implementace rozhraní). Klient tak v requestu vlastně sám uvede, který z možných objektů posílá. objectType zároveň musí být povinná. Příklad pro první z uvedených instancí:
description: Office
type: object
required:
- objectType
properties:
objectType:
type: string
pattern: '^AddresseeBranch$'
Uvádět pattern není povinné. Je však vhodné ho definovat, aby v případě chybné hodnoty zadané klientem nevznikla chyba během zpracování. Takto bude případná chyba odchycena již při validaci requestu.
Pokud chceme aby hodnota property objectType neodpovídala názvu objektu, je třeba definovat mapování mezi hodnotou a názvem objektu. Podrobněji v sekci Mapping Type Names.
Žádné komentáře:
Okomentovat