Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made JSON encoder a public function #443

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 39 additions & 30 deletions lib/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,30 @@ import (

// Module json is a Starlark module of JSON-related functions.
//
// json = module(
// encode,
// decode,
// indent,
// )
// json = module(
// encode,
// decode,
// indent,
// )
//
// def encode(x):
//
// The encode function accepts one required positional argument,
// which it converts to JSON by cases:
// - A Starlark value that implements Go's standard json.Marshal
// interface defines its own JSON encoding.
// - None, True, and False are converted to null, true, and false, respectively.
// - Starlark int values, no matter how large, are encoded as decimal integers.
// Some decoders may not be able to decode very large integers.
// - Starlark float values are encoded using decimal point notation,
// even if the value is an integer.
// It is an error to encode a non-finite floating-point value.
// - Starlark strings are encoded as JSON strings, using UTF-16 escapes.
// - a Starlark IterableMapping (e.g. dict) is encoded as a JSON object.
// It is an error if any key is not a string.
// - any other Starlark Iterable (e.g. list, tuple) is encoded as a JSON array.
// - a Starlark HasAttrs (e.g. struct) is encoded as a JSON object.
// - A Starlark value that implements Go's standard json.Marshal
// interface defines its own JSON encoding.
// - None, True, and False are converted to null, true, and false, respectively.
// - Starlark int values, no matter how large, are encoded as decimal integers.
// Some decoders may not be able to decode very large integers.
// - Starlark float values are encoded using decimal point notation,
// even if the value is an integer.
// It is an error to encode a non-finite floating-point value.
// - Starlark strings are encoded as JSON strings, using UTF-16 escapes.
// - a Starlark IterableMapping (e.g. dict) is encoded as a JSON object.
// It is an error if any key is not a string.
// - any other Starlark Iterable (e.g. list, tuple) is encoded as a JSON array.
// - a Starlark HasAttrs (e.g. struct) is encoded as a JSON object.
//
// It an application-defined type matches more than one the cases describe above,
// (e.g. it implements both Iterable and HasFields), the first case takes precedence.
// Encoding any other value yields an error.
Expand All @@ -58,10 +59,11 @@ import (
//
// The decode function accepts one positional parameter, a JSON string.
// It returns the Starlark value that the string denotes.
// - Numbers are parsed as int or float, depending on whether they
// contain a decimal point.
// - JSON objects are parsed as new unfrozen Starlark dicts.
// - JSON arrays are parsed as new unfrozen Starlark lists.
// - Numbers are parsed as int or float, depending on whether they
// contain a decimal point.
// - JSON objects are parsed as new unfrozen Starlark dicts.
// - JSON arrays are parsed as new unfrozen Starlark lists.
//
// Decoding fails if x is not a valid JSON string.
//
// def indent(str, *, prefix="", indent="\t"):
Expand All @@ -71,7 +73,6 @@ import (
// It accepts one required positional parameter, the JSON string,
// and two optional keyword-only string parameters, prefix and indent,
// that specify a prefix of each new line, and the unit of indentation.
//
var Module = &starlarkstruct.Module{
Name: "json",
Members: starlark.StringDict{
Expand All @@ -81,12 +82,8 @@ var Module = &starlarkstruct.Module{
},
}

func encode(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var x starlark.Value
if err := starlark.UnpackPositionalArgs(b.Name(), args, kwargs, 1, &x); err != nil {
return nil, err
}

// Encodes the given Starlark value as a string in JSON format.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Encode returns the JSON encoding of a Starlark value.

adonovan marked this conversation as resolved.
Show resolved Hide resolved
func EncodeJSON(x starlark.Value) (string, error) {
adonovan marked this conversation as resolved.
Show resolved Hide resolved
buf := new(bytes.Buffer)

var quoteSpace [128]byte
Expand Down Expand Up @@ -221,9 +218,21 @@ func encode(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, k
}

if err := emit(x); err != nil {
return "", err
}
return buf.String(), nil
}

func encode(thread *starlark.Thread, b *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
var x starlark.Value
if err := starlark.UnpackPositionalArgs(b.Name(), args, kwargs, 1, &x); err != nil {
return nil, err
}
s, err := EncodeJSON(x)
if err != nil {
return nil, fmt.Errorf("%s: %v", b.Name(), err)
}
return starlark.String(buf.String()), nil
return starlark.String(s), nil
}

func pointer(i interface{}) unsafe.Pointer {
Expand Down