Opa: JSON Constructing with optional input fields

Created on 6 May 2019  Â·  7Comments  Â·  Source: open-policy-agent/opa

Hello! I have an issue with constructing JSON object in .rego files. I need to create JSON mongodb-selector in rule by provided variables and some variables may be are not provided (optional arguments). But when at least one field value in JSON is not provided - whole rule fails and returned null.
Example:
test policy:

package test

hello[selector] {
  selector = {
    "a": input.a,
        "b": input.b #For example: b is optional and b is not provided now
  }
}

input:

{
  "a": "hello"
}

result:

{
  "result": {
    "hello": []
  }
}

But i need another result, like this:

{
  "result": {
    "hello": {
      "a": "hello"
    }
  }
}

Have .rego any suggestion for this case? Thanks!

design

Most helpful comment

+1 it would be really appreciated to have such feature asap 🙄

All 7 comments

See this playground:

# if b was not provided, this matches
hello[selector] {
  not input.b
  selector = {
      "a": input.a
  }
}

# matches if both a and b are provided
hello[selector] {
  selector = {
    "a": input.a,
    "b": input.b
  }
}

Try playing with the input to see either one of the rules match -- This might not be the most elegant approach, but I hope it serves as an inspiration :wink:

(It might not clarify things, but if it could be written more succinctly, see here.)

Rego doesn't (currently) have a great way to construct JSON values that may be partially undefined. In the long run, I think we need to add a new construct to the language that lets you mark parts of a JSON value as optional (or supply a default) so that construction doesn't fail when a single reference is undefined. This requires a bit of thought though.

In the meantime, there are a few ways you can do this. @srenatus provided one method. Here are two other examples: https://play.openpolicyagent.org/p/Znvn2hm7nR.

@tsandall Thanks a lot!

Just ran into this the other day. I ended up using an object comprehension.

hello[selector] {
  possible_keys := {"a", "b"}
  selector := {x:y |
         possible_keys[x]
         y := input[x]     # if a possible key doesn't exist in input, this will be undefined
   }
}

Just ran into this the other day. I ended up using an object comprehension.

hello[selector] {
  possible_keys := {"a", "b"}
  selector := {x:y |
         possible_keys[x]
         y := input[x]     # if a possible key doesn't exist in input, this will be undefined
   }
}

Thanks for a solution, but i need more flexible syntax, like in javascript. For example, i have this structure

hello[selector] {
selector = {
    "a": input.a,
        "b": {
            "c": input.b #For example: b.c is optional and input.b is not provided now and b in nested object, also b may be in the another field of input, e.x: input.anotherField.b .
     }
  }
}

+1 it would be really appreciated to have such feature asap 🙄

Introducing a new constructor for dictionaries/objects that ignores an
undefined key or value would require a change to evaluation where the
constructor/builtin would be called despite one of its arguments being
undefined.

For example, suppose there were an operator {? for constructing
dictionaries where undefined key/values were ignored. (I don't like this
operator syntactically, but it serves the purpose of the example.)

d := {? "a": "b",
           "c": input.foo}

So if input = {"foo": true} then d == {"a": "b", "c": true}, just like
with the normal operator. But with input = {} then d == {"a": "b"}.

Implementing that would require the evaluator to hand the undefined value
of input.foo over to the constructor, instead of propagating it up to the
dictionary and d like it does today.

On Tue, May 21, 2019 at 6:34 AM Nikolay Aleshkovskiy <
[email protected]> wrote:

+1 it would be really appreciated to have such feature asap 🙄

—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
https://github.com/open-policy-agent/opa/issues/1411?email_source=notifications&email_token=ACMVQK27YZZHEZMGNYR6423PWPF4ZA5CNFSM4HK7X4CKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV3PVHA#issuecomment-494336668,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ACMVQK7H4XNF7G2SJTUM5Q3PWPF4ZANCNFSM4HK7X4CA
.

Was this page helpful?
0 / 5 - 0 ratings