Here is an example of what I mean. https://go.dev/play/p/O6KIsxmSeaN
This is why I wrote a code generator, it's tedious by hand :) On Mon, Dec 26, 2022 at 11:08 AM Marcin Romaszewicz <marc...@gmail.com> wrote: > This is a very annoying problem, and one that we hit a lot in my project ( > https://github.com/deepmap/oapi-codegen), where we generate Go models > from OpenAPI specs, and the OpenAPI "AnyOf" or "OneOf" schema does > precisely this. > > You can partially unmarshal; store your "type" field in a typed variable, > and use json.RawMessage to defer parsing to later, when you know the type. > This still gets annoying, because if your field names are dynamic, you need > to override the default unmarshaling behavior to produce a map of field > names to json.RawMessage. If you jump through these hoops, you can avoid > parsing twice. Once you've partially parsed your object, you can create > some functions on it, such as "AsAtype()" or "AsBType()", which switches on > "type" and returns the correct concrete object. > > On Mon, Dec 26, 2022 at 10:04 AM Andrew Burian <and...@burian.dev> wrote: > >> Hey all, wondering if there's an existing best practice for this so I'm >> not reinventing the wheel. >> >> It's frustratingly common to have APIs where the response JSON can be one >> of several distinct objects, and the indicator of which object has been >> returned is itself a property of the object. >> >> So you might get a `{ "type": "aType", "aField" : ."..." }` or a `{ >> "type": "bType", "bField": "..." }` response from the same API. >> >> What's the best way to deserialize in these situations? >> >> Ideas I've tried so far: >> >> - Unmarhsal twice, once into a struct that just defines the `Type` >> property and ignores all other fields, then again based on the type set >> the >> first time. >> Works, but for large objects it's extremely wasteful. >> >> - Unmarshal into a large struct that defines all possible subtypes as >> anonymous struct fields so their declarations are treated as being on the >> outer struct, then cast to the appropriate type after unmarshaling to mask >> all the unfilled fields. >> Again, works, but feels awful. It also presents a real issue when you >> need to verify that no fields other than the expected fields for the given >> type were present, which you can usually do with >> Decoder.DisallowUnknownFields, but silently succeeds if one of the fields >> is valid for a different object type. >> >> I'm trying to do this as much with stdlib as possible. I've looked into >> some other libraries that make heavy use of JSON decoding and have seen >> both my above ideas, as well as just entirely custom Unmarshaller >> implementations. Hopefully it doesn't come to that. >> >> Cheers, >> Andrew >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/golang-nuts/CAPyCRsvvzzscpgfjj2vPQAi5_DVvrfhxLMu_OhuETzKAd7N1xQ%40mail.gmail.com >> <https://groups.google.com/d/msgid/golang-nuts/CAPyCRsvvzzscpgfjj2vPQAi5_DVvrfhxLMu_OhuETzKAd7N1xQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CA%2Bv29Lue0t62BXrKLYG9CNcd7Bg6XRZJtH61MJG0NFm5jS5NuA%40mail.gmail.com.