package std import ( "fmt" "strconv" "strings" "go.neonxp.dev/json" ) type Factory struct{} func (f *Factory) Produce(typ json.NodeType) (json.Node, error) { switch typ { case json.ObjectType: return ObjectNode{}, nil case json.ArrayType: return &ArrayNode{}, nil case json.StringType: return &StringNode{}, nil case json.NumberType: return &NumberNode{}, nil case json.BooleanType: return &BooleanNode{}, nil case json.NullType: return NullNode{}, nil } 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) Set(k string, v json.Node) { o[k] = v } func (o ObjectNode) Get(k string) (json.Node, bool) { v, ok := o[k] return v, ok } 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.ToJSON())) } return fmt.Sprintf(`{%s}`, strings.Join(res, ",")) } type ArrayNode []json.Node func (o *ArrayNode) Append(v json.Node) { na := append(*o, v) *o = na } func (o *ArrayNode) Index(i int) json.Node { return (*o)[i] } func (o *ArrayNode) Len() int { return len(*o) } func (o *ArrayNode) ToJSON() string { res := make([]string, 0, len(*o)) for _, v := range *o { res = append(res, v.ToJSON()) } return fmt.Sprintf(`[%s]`, strings.Join(res, ",")) } type StringNode struct { Value string } func (o *StringNode) ToJSON() string { return `"` + o.Value + `"` } type NumberNode struct { Value float64 } func (o *NumberNode) ToJSON() string { return strconv.FormatFloat(float64(o.Value), 'g', 15, 64) } type BooleanNode struct { Value bool } func (o BooleanNode) ToJSON() string { if o.Value { return "true" } return "false" } type NullNode struct{} func (o NullNode) ToJSON() string { return "null" }