aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeonXP <i@neonxp.dev>2023-01-04 23:51:40 +0300
committerNeonXP <i@neonxp.dev>2023-01-04 23:51:40 +0300
commit1872e018d1de12793e794fb45d9bbcea569706fe (patch)
tree98229c5398ef42d696d82ee42a14aea2e4c7c3dd
parent67d30e9444c7bdae62906477cafb5f992c5b70e1 (diff)
Added fill to factoryv0.1.2
-rw-r--r--README.md29
-rw-r--r--factory.go17
-rw-r--r--json.go42
-rw-r--r--json_test.go4
-rw-r--r--parser.go20
-rw-r--r--query.go2
-rw-r--r--query_test.go4
-rw-r--r--std/factory.go67
8 files changed, 83 insertions, 102 deletions
diff --git a/README.md b/README.md
index 14995b6..14fe2b1 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/factory.go b/factory.go
index bf44525..9e94e29 100644
--- a/factory.go
+++ b/factory.go
@@ -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 {
diff --git a/json.go b/json.go
index 0ffd7e0..9cfe08c 100644
--- a/json.go
+++ b/json.go
@@ -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
diff --git a/parser.go b/parser.go
index 4e006eb..e902fc3 100644
--- a/parser.go
+++ b/parser.go
@@ -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
}
diff --git a/query.go b/query.go
index 69b778c..18fcfce 100644
--- a/query.go
+++ b/query.go
@@ -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"
}