MCPcopy Create free account
hub / github.com/cogentcore/core / UnmarshalJSON

Method UnmarshalJSON

tree/json.go:52–121  ·  view source on GitHub ↗

UnmarshalJSON unmarshals the node by extracting the nodeType and numChildren fields added by [NodeBase.MarshalJSON] and then updating the node to the correct type and creating the correct number of children. Note that this method can not update the type of the node if it has no parent; to load a roo

(b []byte)

Source from the content-addressed store, hash-verified

50// again through the children of its parent. You do not need to call [UnmarshalRootJSON]
51// or worry about pointers changing if this node is already of the correct type.
52func (n *NodeBase) UnmarshalJSON(b []byte) error {
53 typeStart := bytes.Index(b, []byte(`":`)) + 3
54 typeEnd := bytes.Index(b, []byte(`",`))
55 typeName := string(b[typeStart:typeEnd])
56 // we may end up with an extraneous quote / space at the start
57 typeName = strings.TrimPrefix(strings.TrimSpace(typeName), `"`)
58 typ := types.TypeByName(typeName)
59 if typ == nil {
60 return fmt.Errorf("tree.NodeBase.UnmarshalJSON: type %q not found", typeName)
61 }
62
63 // if our type does not match, we must replace our This to make it match
64 if n.NodeType() != typ {
65 parent := n.Parent
66 index := n.IndexInParent()
67 if index >= 0 {
68 n.Delete()
69 n.This = NewOfType(typ)
70 parent.AsTree().InsertChild(n.This, index)
71 n = n.This.AsTree() // our NodeBase pointer is now different
72 }
73 }
74
75 // We must delete any existing children first.
76 n.DeleteChildren()
77
78 remainder := b[typeEnd+2:]
79 numStart := bytes.Index(remainder, []byte(`"numChildren":`))
80 if numStart >= 0 { // numChildren may not be specified if it is 0
81 numStart += 14 // start of actual number bytes
82 numEnd := bytes.Index(remainder, []byte(`,`))
83 numString := string(remainder[numStart:numEnd])
84 // we may end up with extraneous space at the start
85 numString = strings.TrimSpace(numString)
86 numChildren, err := strconv.Atoi(numString)
87 if err != nil {
88 return err
89 }
90 // We make placeholder NodeBase children that will be replaced
91 // with children of the correct type during their UnmarshalJSON.
92 for range numChildren {
93 New[NodeBase](n)
94 }
95 }
96
97 uv := reflectx.UnderlyingPointer(reflect.ValueOf(n.This))
98 rtyp := unmarshalTypeCache[typeName]
99 if rtyp == nil {
100 // We must create a new type that has the exact same fields as the original type
101 // so that we can unmarshal into it without having infinite recursion on the
102 // UnmarshalJSON method. This works because [reflect.StructOf] does not promote
103 // methods on embedded fields, meaning that the UnmarshalJSON method on the NodeBase
104 // is not carried over and thus is not called, avoiding infinite recursion.
105 uvt := uv.Type().Elem()
106 fields := make([]reflect.StructField, uvt.NumField())
107 for i := range fields {
108 fields[i] = uvt.Field(i)
109 }

Callers 3

lockFileMethod · 0.45
needToReloadMethod · 0.45
UnmarshalRootJSONFunction · 0.45

Calls 15

NodeTypeMethod · 0.95
IndexInParentMethod · 0.95
DeleteMethod · 0.95
DeleteChildrenMethod · 0.95
TypeByNameFunction · 0.92
UnderlyingPointerFunction · 0.92
InsertChildMethod · 0.80
ElemMethod · 0.80
NumFieldMethod · 0.80
FieldMethod · 0.80
NewOfTypeFunction · 0.70
ErrorfMethod · 0.65

Tested by

no test coverage detected