mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-13 03:42:35 -06:00
Add built-ins to un/marshal JSON
This commit is contained in:
@@ -47,6 +47,9 @@ var DefaultBuiltins = [...]*Builtin{
|
||||
|
||||
// Strings
|
||||
Concat, FormatInt, IndexOf, Substring, Lower, Upper, Contains, StartsWith, EndsWith,
|
||||
|
||||
// JSON
|
||||
JSONMarshal, JSONUnmarshal,
|
||||
}
|
||||
|
||||
// BuiltinMap provides a convenient mapping of built-in names to
|
||||
@@ -290,6 +293,24 @@ var Upper = &Builtin{
|
||||
TargetPos: []int{1},
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON
|
||||
*/
|
||||
|
||||
// JSONMarshal serializes the input term.
|
||||
var JSONMarshal = &Builtin{
|
||||
Name: Var("json_marshal"),
|
||||
NumArgs: 2,
|
||||
TargetPos: []int{1},
|
||||
}
|
||||
|
||||
// JSONUnmarshal deserializes the input string.
|
||||
var JSONUnmarshal = &Builtin{
|
||||
Name: Var("json_unmarshal"),
|
||||
NumArgs: 2,
|
||||
TargetPos: []int{1},
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated built-ins.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2017 The OPA Authors. All rights reserved.
|
||||
// Use of this source code is governed by an Apache2
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package topdown
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
"github.com/open-policy-agent/opa/topdown/builtins"
|
||||
"github.com/open-policy-agent/opa/util"
|
||||
)
|
||||
|
||||
func builtinJSONMarshal(a ast.Value) (ast.Value, error) {
|
||||
|
||||
asJSON, err := ast.JSON(a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bs, err := json.Marshal(asJSON)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ast.String(string(bs)), nil
|
||||
}
|
||||
|
||||
func builtinJSONUnmarshal(a ast.Value) (ast.Value, error) {
|
||||
|
||||
str, err := builtins.StringOperand(a, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var x interface{}
|
||||
|
||||
if err := util.UnmarshalJSON([]byte(str), &x); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ast.InterfaceToValue(x)
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterFunctionalBuiltin1(ast.JSONMarshal.Name, builtinJSONMarshal)
|
||||
RegisterFunctionalBuiltin1(ast.JSONUnmarshal.Name, builtinJSONUnmarshal)
|
||||
}
|
||||
@@ -1144,6 +1144,26 @@ func TestTopDownStrings(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopDownJSONBuiltins(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
note string
|
||||
rules []string
|
||||
expected interface{}
|
||||
}{
|
||||
{"marshal", []string{`p = x { json_marshal([{"foo": {1,2,3}}], x) }`}, `"[{\"foo\":[1,2,3]}]"`},
|
||||
{"unmarshal", []string{`p = x { json_unmarshal("[{\"foo\":[1,2,3]}]", x) }`}, `[{"foo": [1,2,3]}]"`},
|
||||
{"unmarshal-non-string", []string{`p = x { json_unmarshal(data.a[0], x) }`}, fmt.Errorf("operand 1 must be string but got number")},
|
||||
}
|
||||
|
||||
data := loadSmallTestData()
|
||||
|
||||
for _, tc := range tests {
|
||||
runTopDownTestCase(t, data, tc.note, tc.rules, tc.expected)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestTopDownEmbeddedVirtualDoc(t *testing.T) {
|
||||
|
||||
compiler := compileModules([]string{
|
||||
|
||||
Reference in New Issue
Block a user