1 package ldmodel 2 3 import ( 4 "github.com/launchdarkly/go-jsonstream/v3/jreader" 5 "github.com/launchdarkly/go-jsonstream/v3/jwriter" 6 ) 7 8 // DataModelSerialization is an abstraction of an encoding for SDK data model objects. 9 // 10 // The ldmodel package defines a standard JSON schema for FeatureFlag and Segment. Currently, this 11 // is the only encoding that is used, so the only implementation of DataModelSerialization is the 12 // one provided by NewDataModelSerialization(), but the interface allows for the possibility that 13 // other encodings will be defined in the future. 14 // 15 // There are also other ways to convert these types to and from the JSON encoding: 16 // 17 // 1. FeatureFlag and Segment define MarshalJSON and UnmarshalJSON methods so that they wil be 18 // correctly encoded or decoded if you call Go's standard json.Marshal or json.Unmarshal. 19 // 20 // 2. There are equivalent methods for encoding and decoding via the go-jsonstream API 21 // (https://pkg.go.dev/github.com/launchdarkly/go-jsonstream/v3). These are used internally by the 22 // SDK to avoid inefficiencies in json.Marshal and json.Unmarshal. 23 // 24 // 3. If the build tag "launchdarkly_easyjson" is set, FeatureFlag and Segment will also define 25 // MarshalEasyJSON and UnmarshalEasyJSON methods for interoperability with the easyjson library. 26 // For details, see the go-jsonstream documentation. 27 // 28 // There is no separately defined encoding for lower-level data model types such as FlagRule, since 29 // there is no guarantee that those will always be represented as individual JSON objects in future 30 // versions of the schema. If you want to create a JSON representation of those data structures you 31 // must define your own type and copy values into it. 32 type DataModelSerialization interface { 33 // MarshalFeatureFlag converts a FeatureFlag into its serialized encoding. 34 MarshalFeatureFlag(item FeatureFlag) ([]byte, error) 35 36 // MarshalSegment converts a Segment into its serialized encoding. 37 MarshalSegment(item Segment) ([]byte, error) 38 39 // UnmarshalFeatureFlag attempts to convert a FeatureFlag from its serialized encoding. 40 UnmarshalFeatureFlag(data []byte) (FeatureFlag, error) 41 42 // UnmarshalFeatureFlag attempts to convert a FeatureFlag from its serialized encoding. 43 UnmarshalSegment(data []byte) (Segment, error) 44 } 45 46 // MarshalFeatureFlagToJSONWriter attempts to convert a FeatureFlag to JSON using the jsonstream API. 47 // For details, see: https://github.com/launchdarkly/go-jsonstream/v3 48 func MarshalFeatureFlagToJSONWriter(item FeatureFlag, writer *jwriter.Writer) { 49 marshalFeatureFlagToWriter(item, writer) 50 } 51 52 // MarshalSegmentToJSONWriter attempts to convert a Segment to JSON using the jsonstream API. 53 // For details, see: https://github.com/launchdarkly/go-jsonstream/v3 54 func MarshalSegmentToJSONWriter(item Segment, writer *jwriter.Writer) { 55 marshalSegmentToWriter(item, writer) 56 } 57 58 // UnmarshalFeatureFlagFromJSONReader attempts to convert a FeatureFlag from JSON using the jsonstream 59 // API. For details, see: https://github.com/launchdarkly/go-jsonstream/v3 60 func UnmarshalFeatureFlagFromJSONReader(reader *jreader.Reader) FeatureFlag { 61 return unmarshalFeatureFlagFromReader(reader) 62 } 63 64 // UnmarshalSegmentFromJSONReader attempts to convert a Segment from JSON using the jsonstream API. 65 // For details, see: https://github.com/launchdarkly/go-jsonstream/v3 66 func UnmarshalSegmentFromJSONReader(reader *jreader.Reader) Segment { 67 return unmarshalSegmentFromReader(reader) 68 } 69 70 type jsonDataModelSerialization struct{} 71 72 // NewJSONDataModelSerialization provides the default JSON encoding for SDK data model objects. 73 // 74 // Always use this rather than relying on json.Marshal() and json.Unmarshal(). The data model 75 // structs are guaranteed to serialize and deserialize correctly with json.Marshal() and 76 // json.Unmarshal(), but JSONDataModelSerialization may be enhanced in the future to use a 77 // more efficient mechanism. 78 func NewJSONDataModelSerialization() DataModelSerialization { 79 return jsonDataModelSerialization{} 80 } 81 82 func (s jsonDataModelSerialization) MarshalFeatureFlag(item FeatureFlag) ([]byte, error) { 83 return marshalFeatureFlag(item) 84 } 85 86 func (s jsonDataModelSerialization) MarshalSegment(item Segment) ([]byte, error) { 87 return marshalSegment(item) 88 } 89 90 func (s jsonDataModelSerialization) UnmarshalFeatureFlag(data []byte) (FeatureFlag, error) { 91 return unmarshalFeatureFlagFromBytes(data) 92 } 93 94 func (s jsonDataModelSerialization) UnmarshalSegment(data []byte) (Segment, error) { 95 return unmarshalSegmentFromBytes(data) 96 } 97 98 // MarshalJSON overrides the default json.Marshal behavior to provide the same marshalling behavior that is 99 // used by NewJSONDataModelSerialization(). 100 func (f FeatureFlag) MarshalJSON() ([]byte, error) { 101 return marshalFeatureFlag(f) 102 } 103 104 // MarshalJSON overrides the default json.Marshal behavior to provide the same marshalling behavior that is 105 // used by NewJSONDataModelSerialization(). 106 func (s Segment) MarshalJSON() ([]byte, error) { 107 return marshalSegment(s) 108 } 109 110 // UnmarshalJSON overrides the default json.Unmarshal behavior to provide the same unmarshalling behavior that 111 // is used by NewJSONDataModelSerialization(). 112 func (f *FeatureFlag) UnmarshalJSON(data []byte) error { 113 result, err := unmarshalFeatureFlagFromBytes(data) 114 if err == nil { 115 *f = result 116 } 117 return err 118 } 119 120 // UnmarshalJSON overrides the default json.Unmarshal behavior to provide the same unmarshalling behavior that 121 // is used by NewJSONDataModelSerialization(). 122 func (s *Segment) UnmarshalJSON(data []byte) error { 123 result, err := unmarshalSegmentFromBytes(data) 124 if err == nil { 125 *s = result 126 } 127 return err 128 } 129