|
| 1 | +package discriminator |
| 2 | + |
| 3 | +import ( |
| 4 | + "encoding/json" |
| 5 | + "fmt" |
| 6 | +) |
| 7 | + |
| 8 | +// Note: This package demonstrates client-side usage of discriminators with allOf. |
| 9 | +// Additional client examples and tests: ./strict-server/client_test.go |
| 10 | +// Server-side polymorphism usage: ./strict-server/server_test.go |
| 11 | + |
| 12 | +// ExamplePetDiscriminator demonstrates standard one-level inheritance discriminator usage. |
| 13 | +func ExamplePetDiscriminator() { |
| 14 | + catJSON := `{"petType": "cat", "name": "Fluffy", "meow": true}` |
| 15 | + |
| 16 | + var pet Pet |
| 17 | + if err := json.Unmarshal([]byte(catJSON), &pet); err != nil { |
| 18 | + panic(err) |
| 19 | + } |
| 20 | + |
| 21 | + fmt.Printf("Pet: %s (type: %s)\n", pet.Name, pet.Discriminator()) |
| 22 | + |
| 23 | + // IsCat is here only for clarity. Use only `value, err := pet.AsCat()` for concrete type. |
| 24 | + if pet.IsCat() { |
| 25 | + cat, _ := pet.AsCat() |
| 26 | + fmt.Printf("Cat meows: %v\n", *cat.Meow) |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +// ExampleValueByDiscriminator demonstrates ValueByDiscriminator + type switch pattern. |
| 31 | +// For client-side processing, Is<Type>()/As<Type>() is often more convenient. |
| 32 | +func ExampleValueByDiscriminator() { |
| 33 | + catJSON := `{"petType": "cat", "name": "Whiskers", "meow": true}` |
| 34 | + |
| 35 | + var pet Pet |
| 36 | + if err := json.Unmarshal([]byte(catJSON), &pet); err != nil { |
| 37 | + panic(err) |
| 38 | + } |
| 39 | + |
| 40 | + value, err := pet.ValueByDiscriminator() |
| 41 | + if err != nil { |
| 42 | + panic(err) |
| 43 | + } |
| 44 | + |
| 45 | + switch v := value.(type) { |
| 46 | + case *Cat: |
| 47 | + fmt.Printf("This is a cat: %s (meows: %v)\n", v.Name, *v.Meow) |
| 48 | + case *Dog: |
| 49 | + fmt.Printf("This is a dog: %s (barks: %v)\n", v.Name, *v.Bark) |
| 50 | + default: |
| 51 | + fmt.Printf("Unknown pet type: %T\n", v) |
| 52 | + } |
| 53 | +} |
| 54 | + |
| 55 | +// ExampleNestedDiscriminators demonstrates multi-level discriminator hierarchy. |
| 56 | +func ExampleNestedDiscriminators() { |
| 57 | + houseCatJSON := `{ |
| 58 | + "animalType": "domestic", |
| 59 | + "domesticType": "housecat", |
| 60 | + "name": "Whiskers", |
| 61 | + "owner": "John", |
| 62 | + "indoor": true |
| 63 | + }` |
| 64 | + |
| 65 | + var animal Animal |
| 66 | + if err := json.Unmarshal([]byte(houseCatJSON), &animal); err != nil { |
| 67 | + panic(err) |
| 68 | + } |
| 69 | + |
| 70 | + fmt.Printf("Animal: %s (type: %s)\n", animal.Name, animal.Discriminator()) |
| 71 | + |
| 72 | + // Navigate through hierarchy or use `value, err := As<Type>` without Is<Type>. |
| 73 | + // The hierarchy navigation is shown for clarity. |
| 74 | + if animal.IsDomesticAnimal() { |
| 75 | + domestic, _ := animal.AsDomesticAnimal() |
| 76 | + fmt.Printf("Domestic type: %s, Owner: %s\n", domestic.Discriminator(), *domestic.Owner) |
| 77 | + |
| 78 | + // Further navigate to concrete type |
| 79 | + if domestic.IsHouseCat() { |
| 80 | + cat, _ := domestic.AsHouseCat() |
| 81 | + fmt.Printf("House cat, Indoor: %v\n", *cat.Indoor) |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + // Another example: Lion |
| 86 | + lionJSON := `{ |
| 87 | + "animalType": "wild", |
| 88 | + "wildType": "lion", |
| 89 | + "name": "Simba", |
| 90 | + "habitat": "Savanna", |
| 91 | + "maneColor": "golden" |
| 92 | + }` |
| 93 | + |
| 94 | + var wildAnimal Animal |
| 95 | + if err := json.Unmarshal([]byte(lionJSON), &wildAnimal); err != nil { |
| 96 | + panic(err) |
| 97 | + } |
| 98 | + |
| 99 | + if wildAnimal.IsWildAnimal() { |
| 100 | + wild, _ := wildAnimal.AsWildAnimal() |
| 101 | + fmt.Printf("\nWild animal: %s, habitat: %s\n", wild.Name, *wild.Habitat) |
| 102 | + |
| 103 | + if wild.IsLion() { |
| 104 | + lion, _ := wild.AsLion() |
| 105 | + fmt.Printf("Lion with mane color: %s\n", lion.ManeColor) |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | + |
| 110 | +// ExampleProcessingArray demonstrates filtering arrays of polymorphic objects. |
| 111 | +func ExampleProcessingArray() { |
| 112 | + animalsJSON := `[ |
| 113 | + {"animalType": "domestic", "domesticType": "housecat", "name": "Whiskers", "owner": "Alice", "indoor": true}, |
| 114 | + {"animalType": "wild", "wildType": "lion", "name": "Simba", "habitat": "Savanna"}, |
| 115 | + {"animalType": "domestic", "domesticType": "housedog", "name": "Buddy", "owner": "Bob", "trained": true} |
| 116 | + ]` |
| 117 | + |
| 118 | + var animals []Animal |
| 119 | + if err := json.Unmarshal([]byte(animalsJSON), &animals); err != nil { |
| 120 | + panic(err) |
| 121 | + } |
| 122 | + |
| 123 | + // Select cats |
| 124 | + var cats []*HouseCat |
| 125 | + for _, animal := range animals { |
| 126 | + if animal.IsDomesticAnimal() { |
| 127 | + domestic, _ := animal.AsDomesticAnimal() |
| 128 | + |
| 129 | + if domestic.IsHouseCat() { |
| 130 | + cat, _ := domestic.AsHouseCat() |
| 131 | + cats = append(cats, cat) |
| 132 | + } |
| 133 | + } |
| 134 | + } |
| 135 | + fmt.Printf("Found %d cats\n", len(cats)) |
| 136 | +} |
| 137 | + |
| 138 | +// ExampleMultipleDiscriminators demonstrates handling types with multiple inherited discriminators. |
| 139 | +func ExampleMultipleDiscriminators() { |
| 140 | + mouseJSON := `{ |
| 141 | + "petType": "mouse", |
| 142 | + "name": "Jerry", |
| 143 | + "pestType": "rodent", |
| 144 | + "habitat": "house", |
| 145 | + "tailLength": 5.5 |
| 146 | + }` |
| 147 | + |
| 148 | + // Deserialize into Pet (polymorphic base type) |
| 149 | + var pet Pet |
| 150 | + if err := json.Unmarshal([]byte(mouseJSON), &pet); err != nil { |
| 151 | + panic(err) |
| 152 | + } |
| 153 | + |
| 154 | + fmt.Printf("Pet: %s (type: %s)\n", pet.Name, pet.Discriminator()) |
| 155 | + |
| 156 | + // Convert to Mouse |
| 157 | + mouse, _ := pet.AsMouse() |
| 158 | + |
| 159 | + // Mouse has both discriminator properties as regular fields |
| 160 | + fmt.Printf("Mouse name: %s\n", mouse.Name) |
| 161 | + fmt.Printf("Pet type: %s\n", mouse.PetType) |
| 162 | + fmt.Printf("Pest type: %s\n", mouse.PestType) |
| 163 | + fmt.Printf("Habitat: %s\n", mouse.Habitat) |
| 164 | + if mouse.TailLength != nil { |
| 165 | + fmt.Printf("Tail length: %.1f\n", *mouse.TailLength) |
| 166 | + } |
| 167 | +} |
0 commit comments