diff options
-rw-r--r-- | README.md | 29 | ||||
-rw-r--r-- | factory.go | 17 | ||||
-rw-r--r-- | json.go | 42 | ||||
-rw-r--r-- | json_test.go | 4 | ||||
-rw-r--r-- | parser.go | 20 | ||||
-rw-r--r-- | query.go | 2 | ||||
-rw-r--r-- | query_test.go | 4 | ||||
-rw-r--r-- | std/factory.go | 67 |
8 files changed, 83 insertions, 102 deletions
@@ -63,21 +63,24 @@ std.ObjectNode{ ## Своя фабрика ``` -// Непосредственно фабрика возвращающая заготовки нужного типа -type NodeFactory func(typ NodeType) (Node, error) +type Factory interface { + // Непосредственно фабрика возвращающая заготовки нужного типа + Produce(typ NodeType) (Node, error) + // Заполнение заготовки определенного типа соответствующим ей значением + Fill(n Node, value any) +} type Node interface { - String() string + // Возвращает json представление узла + ToJSON() string } -// Имплементация узла объекта type ObjectNode interface { Node - SetKetValue(k string, v Node) - GetByKey(k string) (Node, bool) + Set(k string, v Node) + Get(k string) (Node, bool) } -// Имлементация узла массива type ArrayNode interface { Node Append(v Node) @@ -85,29 +88,18 @@ type ArrayNode interface { Len() int } -// Имплементация узла строки type StringNode interface { Node - SetString(v string) - GetString() string } - -// Имплементация узла числа type NumberNode interface { Node - SetNumber(v float64) - GetNumber() float64 } -// Имплементация узла булевого типа type BooleanNode interface { Node - SetBool(v bool) - GetBool() bool } -// Имплементация null type NullNode interface { Node } @@ -118,3 +110,4 @@ type AcceptParent interface { } ``` +[Пример реализации самой простой фабрики и типов](/std/factory.go)
\ No newline at end of file @@ -1,15 +1,18 @@ package json -type NodeFactory func(typ NodeType) (Node, error) +type Factory interface { + Produce(typ NodeType) (Node, error) + Fill(n Node, value any) +} type Node interface { - String() string + ToJSON() string } type ObjectNode interface { Node - SetKeyValue(k string, v Node) - GetByKey(k string) (Node, bool) + Set(k string, v Node) + Get(k string) (Node, bool) } type ArrayNode interface { @@ -21,20 +24,14 @@ type ArrayNode interface { type StringNode interface { Node - SetString(v string) - GetString() string } type NumberNode interface { Node - SetNumber(v float64) - GetNumber() float64 } type BooleanNode interface { Node - SetBool(v bool) - GetBool() bool } type NullNode interface { @@ -7,7 +7,7 @@ import ( ) type JSON struct { - Factory NodeFactory + Factory Factory } func (j *JSON) Unmarshal(input string) (Node, error) { @@ -25,61 +25,55 @@ func (j *JSON) MustUnmarshal(input string) Node { } func (j *JSON) Marshal(n Node) string { - return n.String() + return n.ToJSON() } func (j *JSON) Node(value any) (Node, error) { switch value := value.(type) { case string: - n, err := j.Factory(StringType) + n, err := j.Factory.Produce(StringType) if err != nil { return nil, err } - n.(StringNode).SetString(value) + j.Factory.Fill(n, value) return n, nil case float64: - n, err := j.Factory(NumberType) + n, err := j.Factory.Produce(NumberType) if err != nil { return nil, err } - n.(NumberNode).SetNumber(value) + j.Factory.Fill(n, value) return n, nil case int: - n, err := j.Factory(NumberType) + n, err := j.Factory.Produce(NumberType) if err != nil { return nil, err } - n.(NumberNode).SetNumber(float64(value)) + j.Factory.Fill(n, float64(value)) return n, nil case bool: - n, err := j.Factory(BooleanType) + n, err := j.Factory.Produce(BooleanType) if err != nil { return nil, err } - n.(BooleanNode).SetBool(value) + j.Factory.Fill(n, value) return n, nil case nil: - return j.Factory(NullType) + return j.Factory.Produce(NullType) case map[string]Node: - n, err := j.Factory(ObjectType) + n, err := j.Factory.Produce(ObjectType) if err != nil { return nil, err } - on := n.(ObjectNode) - for k, v := range value { - on.SetKeyValue(k, v) - } - return on, nil + j.Factory.Fill(n, value) + return n, nil case []Node: - n, err := j.Factory(ArrayType) + n, err := j.Factory.Produce(ArrayType) if err != nil { return nil, err } - an := n.(ArrayNode) - for _, v := range value { - an.Append(v) - } - return an, nil + j.Factory.Fill(n, value) + return n, nil default: return nil, fmt.Errorf("invalid type %t", value) } @@ -93,7 +87,7 @@ func (j *JSON) MustNode(value any) Node { return n } -func New(factory NodeFactory) *JSON { +func New(factory Factory) *JSON { return &JSON{ Factory: factory, } diff --git a/json_test.go b/json_test.go index b058417..2b6621e 100644 --- a/json_test.go +++ b/json_test.go @@ -10,7 +10,7 @@ import ( func TestJSON_Unmarshal(t *testing.T) { j := &json.JSON{ - Factory: std.Factory, + Factory: &std.Factory{}, } type args struct { input string @@ -95,7 +95,7 @@ func TestJSON_Unmarshal(t *testing.T) { func TestJSON_Marshal(t *testing.T) { j := &json.JSON{ - Factory: std.Factory, + Factory: &std.Factory{}, } type args struct { n json.Node @@ -16,7 +16,7 @@ func (j *JSON) parse(ch chan lexer.Lexem) (Node, error) { func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Node, error) { switch l.Type { case lexer.LString: - c, err := j.Factory(StringType) + c, err := j.Factory.Produce(StringType) if err != nil { return nil, err } @@ -24,14 +24,14 @@ func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Nod c.SetParent(parent) } child := c.(StringNode) - child.SetString(strings.Trim(l.Value, `"`)) + j.Factory.Fill(child, strings.Trim(l.Value, `"`)) return child, nil case lexer.LNumber: num, err := strconv.ParseFloat(l.Value, 64) if err != nil { return nil, err } - c, err := j.Factory(NumberType) + c, err := j.Factory.Produce(NumberType) if err != nil { return nil, err } @@ -39,11 +39,11 @@ func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Nod c.SetParent(parent) } child := c.(NumberNode) - child.SetNumber(num) + j.Factory.Fill(child, num) return child, nil case lexer.LBoolean: b := strings.ToLower(l.Value) == "true" - c, err := j.Factory(BooleanType) + c, err := j.Factory.Produce(BooleanType) if err != nil { return nil, err } @@ -51,7 +51,7 @@ func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Nod c.SetParent(parent) } child := c.(BooleanNode) - child.SetBool(b) + j.Factory.Fill(child, b) return child, nil case lexer.LObjectStart: child, err := j.parseObject(parent, ch) @@ -66,7 +66,7 @@ func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Nod } return child, nil case lexer.LNull: - c, err := j.Factory(NullType) + c, err := j.Factory.Produce(NullType) if err != nil { return nil, err } @@ -80,7 +80,7 @@ func (j *JSON) createChild(parent Node, l lexer.Lexem, ch chan lexer.Lexem) (Nod } func (j *JSON) parseObject(parent Node, ch chan lexer.Lexem) (ObjectNode, error) { - c, err := j.Factory(ObjectType) + c, err := j.Factory.Produce(ObjectType) if err != nil { return nil, err } @@ -102,14 +102,14 @@ func (j *JSON) parseObject(parent Node, ch chan lexer.Lexem) (ObjectNode, error) if err != nil { return nil, err } - n.SetKeyValue(nextKey, child) + n.Set(nextKey, child) } } return nil, fmt.Errorf("unexpected end of object") } func (j *JSON) parseArray(parent Node, ch chan lexer.Lexem) (ArrayNode, error) { - c, err := j.Factory(ArrayType) + c, err := j.Factory.Produce(ArrayType) if err != nil { return nil, err } @@ -13,7 +13,7 @@ func Query(parent Node, path []string) (Node, error) { head, rest := path[0], path[1:] switch parent := parent.(type) { case ObjectNode: - next, ok := parent.GetByKey(head) + next, ok := parent.Get(head) if !ok { return nil, fmt.Errorf("key %s not found at object %v", head, parent) } diff --git a/query_test.go b/query_test.go index 44383de..be012e2 100644 --- a/query_test.go +++ b/query_test.go @@ -41,7 +41,7 @@ func TestMustQuery(t *testing.T) { { name: "find in object", args: args{ - parent: json.New(std.Factory).MustUnmarshal(jsonString), + parent: json.New(&std.Factory{}).MustUnmarshal(jsonString), path: []string{"object", "object 2", "three"}, }, want: &std.StringNode{Value: "four"}, @@ -49,7 +49,7 @@ func TestMustQuery(t *testing.T) { { name: "find in array", args: args{ - parent: json.New(std.Factory).MustUnmarshal(jsonString), + parent: json.New(&std.Factory{}).MustUnmarshal(jsonString), path: []string{"array", "[4]", "five"}, }, want: &std.StringNode{Value: "six"}, diff --git a/std/factory.go b/std/factory.go index 11c3de1..41085a6 100644 --- a/std/factory.go +++ b/std/factory.go @@ -8,7 +8,9 @@ import ( "go.neonxp.dev/json" ) -func Factory(typ json.NodeType) (json.Node, error) { +type Factory struct{} + +func (f *Factory) Produce(typ json.NodeType) (json.Node, error) { switch typ { case json.ObjectType: return ObjectNode{}, nil @@ -26,21 +28,40 @@ func Factory(typ json.NodeType) (json.Node, error) { return nil, fmt.Errorf("unknown type: %s", typ) } +func (f *Factory) Fill(n json.Node, value any) { + switch n := n.(type) { + case *ObjectNode: + for k, v := range value.(map[string]json.Node) { + n.Set(k, v) + } + case *ArrayNode: + for _, v := range value.([]json.Node) { + n.Append(v) + } + case *StringNode: + n.Value = value.(string) + case *NumberNode: + n.Value = value.(float64) + case *BooleanNode: + n.Value = value.(bool) + } +} + type ObjectNode map[string]json.Node -func (o ObjectNode) SetKeyValue(k string, v json.Node) { +func (o ObjectNode) Set(k string, v json.Node) { o[k] = v } -func (o ObjectNode) GetByKey(k string) (json.Node, bool) { +func (o ObjectNode) Get(k string) (json.Node, bool) { v, ok := o[k] return v, ok } -func (o ObjectNode) String() string { +func (o ObjectNode) ToJSON() string { res := make([]string, 0, len(o)) for k, n := range o { - res = append(res, fmt.Sprintf(`"%s":%s`, k, n.String())) + res = append(res, fmt.Sprintf(`"%s":%s`, k, n.ToJSON())) } return fmt.Sprintf(`{%s}`, strings.Join(res, ",")) } @@ -60,10 +81,10 @@ func (o *ArrayNode) Len() int { return len(*o) } -func (o *ArrayNode) String() string { +func (o *ArrayNode) ToJSON() string { res := make([]string, 0, len(*o)) for _, v := range *o { - res = append(res, v.String()) + res = append(res, v.ToJSON()) } return fmt.Sprintf(`[%s]`, strings.Join(res, ",")) } @@ -72,15 +93,7 @@ type StringNode struct { Value string } -func (o *StringNode) SetString(v string) { - o.Value = v -} - -func (o *StringNode) GetString() string { - return o.Value -} - -func (o *StringNode) String() string { +func (o *StringNode) ToJSON() string { return `"` + o.Value + `"` } @@ -88,15 +101,7 @@ type NumberNode struct { Value float64 } -func (o *NumberNode) SetNumber(v float64) { - o.Value = v -} - -func (o *NumberNode) GetNumber() float64 { - return o.Value -} - -func (o *NumberNode) String() string { +func (o *NumberNode) ToJSON() string { return strconv.FormatFloat(float64(o.Value), 'g', 15, 64) } @@ -104,15 +109,7 @@ type BooleanNode struct { Value bool } -func (o *BooleanNode) SetBool(v bool) { - o.Value = v -} - -func (o *BooleanNode) GetBool() bool { - return o.Value -} - -func (o BooleanNode) String() string { +func (o BooleanNode) ToJSON() string { if o.Value { return "true" } @@ -121,6 +118,6 @@ func (o BooleanNode) String() string { type NullNode struct{} -func (o NullNode) String() string { +func (o NullNode) ToJSON() string { return "null" } |