diff --git a/eval/builtin_func.go b/eval/builtin_func.go index a558a4c5..88c5a23f 100644 --- a/eval/builtin_func.go +++ b/eval/builtin_func.go @@ -62,6 +62,7 @@ func init() { &BuiltinFn{"put-all", wrapFn(putAll)}, &BuiltinFn{"unpack", wrapFn(unpack)}, + &BuiltinFn{"to-json", wrapFn(toJSON)}, &BuiltinFn{"from-json", wrapFn(fromJSON)}, &BuiltinFn{"kind-of", kindOf}, @@ -337,6 +338,18 @@ func unpack(ec *EvalCtx) { } } +// toJSON converts a stream of Value's to JSON data. +func toJSON(ec *EvalCtx) { + in := ec.ports[0].Chan + out := ec.ports[1].File + + enc := json.NewEncoder(out) + for v := range in { + err := enc.Encode(v) + maybeThrow(err) + } +} + // fromJSON parses a stream of JSON data into Value's. func fromJSON(ec *EvalCtx) { in := ec.ports[0].File diff --git a/eval/list.go b/eval/list.go index 4d650ff6..b75c8812 100644 --- a/eval/list.go +++ b/eval/list.go @@ -2,6 +2,7 @@ package eval import ( "bytes" + "encoding/json" "errors" "strconv" "strings" @@ -42,6 +43,10 @@ func (l List) Repr(indent int) string { return b.String() } +func (l List) MarshalJSON() ([]byte, error) { + return json.Marshal(*l.inner) +} + func (l List) Len() int { return len(*l.inner) } diff --git a/eval/map.go b/eval/map.go index ebf9655e..0f76d05b 100644 --- a/eval/map.go +++ b/eval/map.go @@ -1,6 +1,9 @@ package eval -import "errors" +import ( + "encoding/json" + "errors" +) // Map is a map from string to Value. type Map struct { @@ -21,6 +24,15 @@ func (Map) Kind() string { return "map" } +func (m Map) MarshalJSON() ([]byte, error) { + // XXX Not the most efficient way. + mm := map[string]Value{} + for k, v := range *m.inner { + mm[ToString(k)] = v + } + return json.Marshal(mm) +} + func (m Map) Repr(indent int) string { var builder MapReprBuilder builder.Indent = indent