1package stdlib
2
3import (
4	"github.com/zclconf/go-cty/cty"
5	"github.com/zclconf/go-cty/cty/function"
6	"github.com/zclconf/go-cty/cty/json"
7)
8
9var JSONEncodeFunc = function.New(&function.Spec{
10	Params: []function.Parameter{
11		{
12			Name:             "val",
13			Type:             cty.DynamicPseudoType,
14			AllowDynamicType: true,
15			AllowNull:        true,
16		},
17	},
18	Type: function.StaticReturnType(cty.String),
19	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
20		val := args[0]
21		if !val.IsWhollyKnown() {
22			// We can't serialize unknowns, so if the value is unknown or
23			// contains any _nested_ unknowns then our result must be
24			// unknown.
25			return cty.UnknownVal(retType), nil
26		}
27
28		if val.IsNull() {
29			return cty.StringVal("null"), nil
30		}
31
32		buf, err := json.Marshal(val, val.Type())
33		if err != nil {
34			return cty.NilVal, err
35		}
36
37		return cty.StringVal(string(buf)), nil
38	},
39})
40
41var JSONDecodeFunc = function.New(&function.Spec{
42	Params: []function.Parameter{
43		{
44			Name: "str",
45			Type: cty.String,
46		},
47	},
48	Type: func(args []cty.Value) (cty.Type, error) {
49		str := args[0]
50		if !str.IsKnown() {
51			return cty.DynamicPseudoType, nil
52		}
53
54		buf := []byte(str.AsString())
55		return json.ImpliedType(buf)
56	},
57	Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
58		buf := []byte(args[0].AsString())
59		return json.Unmarshal(buf, retType)
60	},
61})
62
63// JSONEncode returns a JSON serialization of the given value.
64func JSONEncode(val cty.Value) (cty.Value, error) {
65	return JSONEncodeFunc.Call([]cty.Value{val})
66}
67
68// JSONDecode parses the given JSON string and, if it is valid, returns the
69// value it represents.
70//
71// Note that applying JSONDecode to the result of JSONEncode may not produce
72// an identically-typed result, since JSON encoding is lossy for cty Types.
73// The resulting value will consist only of primitive types, object types, and
74// tuple types.
75func JSONDecode(str cty.Value) (cty.Value, error) {
76	return JSONDecodeFunc.Call([]cty.Value{str})
77}
78