/
json_serializable.go
86 lines (72 loc) · 2.32 KB
/
json_serializable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package iotago
import (
"encoding/json"
"errors"
"fmt"
"github.com/iotaledger/hive.go/serializer/v2"
)
var (
// ErrInvalidJSON gets returned when invalid JSON is tried to get parsed.
ErrInvalidJSON = errors.New("invalid json")
)
// JSONSerializable is an object which can return a Serializable.
type JSONSerializable interface {
// ToSerializable returns the Serializable form of the JSONSerializable.
ToSerializable() (serializer.Serializable, error)
}
// JSONObjectEnvelope defines the envelope for looking-ahead an object's type
// before deserializing it to its actual object.
type JSONObjectEnvelope struct {
Type int `json:"type"`
}
// JSONSerializableSelectorFunc is a function that given a type int, returns an empty instance of the given underlying type.
// If the type doesn't resolve, an error is returned.
type JSONSerializableSelectorFunc func(ty int) (JSONSerializable, error)
// DeserializeObjectFromJSON reads out the type of the given raw json message,
// then selects the appropriate object type and deserializes the given *json.RawMessage into it.
func DeserializeObjectFromJSON(raw *json.RawMessage, selector JSONSerializableSelectorFunc) (JSONSerializable, error) {
j, err := raw.MarshalJSON()
if err != nil {
return nil, err
}
envelope := &JSONObjectEnvelope{}
if err := json.Unmarshal(j, envelope); err != nil {
return nil, err
}
obj, err := selector(envelope.Type)
if err != nil {
return nil, err
}
rawJSON, err := raw.MarshalJSON()
if err != nil {
return nil, err
}
if err := json.Unmarshal(rawJSON, obj); err != nil {
return nil, err
}
return obj, nil
}
func serializablesToJSONRawMsgs(seris serializer.Serializables) ([]*json.RawMessage, error) {
msgs := make([]*json.RawMessage, len(seris))
for i, seri := range seris {
jSeri, err := seri.MarshalJSON()
if err != nil {
return nil, err
}
rawSeriJson := json.RawMessage(jSeri)
msgs[i] = &rawSeriJson
}
return msgs, nil
}
func jsonRawMsgsToSerializables(msgs []*json.RawMessage, selector JSONSerializableSelectorFunc) (serializer.Serializables, error) {
seris := make(serializer.Serializables, len(msgs))
for i, ele := range msgs {
jSeri, _ := DeserializeObjectFromJSON(ele, selector)
seri, err := jSeri.ToSerializable()
if err != nil {
return nil, fmt.Errorf("pos %d: %w", i, err)
}
seris[i] = seri
}
return seris, nil
}