1// Copyright (c) 2021, Peter Ohler, All rights reserved.
2
3package oj_test
4
5import (
6	"fmt"
7
8	"github.com/ohler55/ojg"
9	"github.com/ohler55/ojg/alt"
10	"github.com/ohler55/ojg/oj"
11)
12
13// Encode and decode slice of interfaces.
14
15type Animal interface {
16	Kind() string
17}
18
19type Dog struct {
20	Size string
21}
22
23func (d *Dog) Kind() string {
24	return fmt.Sprintf("%s dog", d.Size)
25}
26
27type Cat struct {
28	Color string
29}
30
31func (c *Cat) Kind() string {
32	return fmt.Sprintf("%s cat", c.Color)
33}
34
35func ExampleUnmarshal_interface() {
36	pets := []Animal{&Dog{Size: "big"}, &Cat{Color: "black"}}
37
38	// Encode and use a create key to identify the encoded type.
39	b, err := oj.Marshal(pets, &ojg.Options{CreateKey: "^", Sort: true})
40	if err != nil {
41		panic(err)
42	}
43	// Sort the object members in the output for repeatability.
44	fmt.Printf("as JSON: %s\n", b)
45
46	// Create a new Recomposer. This can be use over and over again. Register
47	// the types with a nil creation function to let reflection do the work
48	// since the types are exported.
49	var r *alt.Recomposer
50	if r, err = alt.NewRecomposer("^", map[interface{}]alt.RecomposeFunc{&Dog{}: nil, &Cat{}: nil}); err != nil {
51		panic(err)
52	}
53	var result interface{}
54	if err = oj.Unmarshal(b, &result, r); err != nil {
55		panic(err)
56	}
57	list, _ := result.([]interface{})
58	for _, item := range list {
59		animal, _ := item.(Animal)
60		fmt.Printf("  %s\n", animal.Kind())
61	}
62	// Unmarshal with a typed target.
63	var animals []Animal
64	if err = oj.Unmarshal(b, &animals, r); err != nil {
65		panic(err)
66	}
67	fmt.Println("Unmarshal into a target struct")
68	for _, animal := range animals {
69		fmt.Printf("  %T - %s\n", animal, animal.Kind())
70	}
71
72	// Output:
73	// as JSON: [{"^":"Dog","size":"big"},{"^":"Cat","color":"black"}]
74	//   big dog
75	//   black cat
76	// Unmarshal into a target struct
77	//   *oj_test.Dog - big dog
78	//   *oj_test.Cat - black cat
79}
80