Giter Site home page Giter Site logo

json-e / json-e Goto Github PK

View Code? Open in Web Editor NEW
148.0 12.0 84.0 9.62 MB

A data-structure parameterization system written for embedding context in JSON objects

Home Page: https://json-e.js.org/

License: Mozilla Public License 2.0

JavaScript 17.50% Python 19.51% Shell 0.97% Go 24.45% Rust 37.58%
json expression-language string-interpolation template untrusted-values yaml

json-e's Introduction

JSON-e

JSON-e is a data-structure parameterization system for embedding context in JSON objects.

The central idea is to treat a data structure as a "template" and transform it, using another data structure as context, to produce an output data structure.

There are countless libraries to do this with strings, such as mustache. What makes JSON-e unique is that it operates on data structures, not on their textual representation. This allows input to be written in a number of formats (JSON, YAML, etc.) or even generated dynamically. It also means that the output cannot be "invalid", even when including large chunks of contextual data.

JSON-e is also designed to be safe for use on untrusted data. It never uses eval or any other function that might result in arbitrary code execution. It also disallows unbounded iteration, so any JSON-e rendering operation will finish in finite time.

Language Definition and Implementations

This repository both defines the JSON-e language and contains several implementations of that language.

The language definition is embodied in ./specification.yml and the documentation for the language constructs.

The language and implementations are all versioned together, following semantic versioning. Breaking changes to the language specification are not common, and typically result from bugfixes rather than new features. Generally, you may consider the language stable.

Any discrepancy in behavior between the implementations that is not documented as undefined behavior is considered a bug. If fixing that bug can cause backward incompatibility in an implementation, then the change may be considered breaking and be released with a new major version.

Other Implementations

Full Documentation

See json-e.js.org.

Changes

See CHANGELOG.rst for the changes in each version of this library.

In Action

Where is JSON-e used?

  • AlterSchema specifies upgrades as a set of declarative transformation rules written in JSON Schema itself and JSON-e.
  • Taskcluster uses JSON-e extensively to generate task definitions from various JSON-shaped inputs such as GitHub events.

(feel free to submit a PR to add your project here)

json-e's People

Contributors

alexandrasp avatar alopezz avatar biboswan avatar cronik avatar dependabot[bot] avatar djmitche avatar escapewindow avatar gregsdennis avatar hammad13060 avatar imbstack avatar janiceshiu avatar jonasfj avatar jwhitlock avatar lauryndbrown avatar mkantor avatar nicrii avatar noahlaux avatar osumgbachiamaka avatar owlishdeveloper avatar petemoore avatar prachi1210 avatar renovate-bot avatar richardgreg avatar skapfer avatar tadpol avatar terrameijar avatar the-question avatar thenavigat avatar ydidwania avatar zacho2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-e's Issues

fix, document truthiness, falsiness

❌ indicates not currently working, and marked as a todo in the specification. I've chosen to follow python semantics here since that's what our expression language is mimicking.

  • empty string -> false
  • nonempty string -> true
  • empty array -> false ❌
  • nonempty array -> true
  • empty object -> false ❌
  • nonempty object -> true
  • null -> false

Automatically ensure bundle is updated

We don't want to do automated check-ins of an updated bundle.js, but we can add an automated test to ensure that re-generating bundle.js doesn't generate any diffs. Running that check on PRs will catch any changes that forget to update it.

Compare things deeply

That JS does weird undefined things when you use == on objects or arrays is a JS bug, and we shouldn't propagate that into JSON-e. Instead, we should do deep object comparisons.

Change repository settings for website

Repository settings should be changed to display the website in the docs/ directory in the master branch. Consequently, the gh-pages branch should also be deleted.

Demo website for json-e

We should make a github pages site that looks this:

https://img42.com/0b78N

With a live "try it" editor... that way we can easily test bugs etc...

Only support unicode strings

We should reject bytestrings outright and always expect unicode input.

That's a little tricky with py2/py3 compatibility, but it's not so hard.

question: rename $dumps -> $json

I just realized that dumps might only be obvious to python users. And even then they only know it as json.dumps.

Should we consider renaming the construct {$json: ...} or {$stringify: ...}, any other ideas?

Define behavior for accessing undefined keys in an object

Example: {$eval: '({"test": 4}).foo'}

Questions:

  • Does this eval to null
  • Does it throw an error
  • How do you get an object with default like x.foo || 'default-value' in js

As @djmitche said in comment:

So I can see a few options:

  • x['foo'] and x.foo are null - but this will not "go away" when users want it to
  • x['foo'] and x.foo are a delete marker - this will require handling delete markers within the expression language, where currently they're only handled in array/object construction
  • x['foo'] and x.foo are errors, but get(x, 'foo', 123) is 123, and the get built-in always requires that third argument.
    Preferences?

I don't know how feasible it is... But I'm tempted to suggest an or operator... as in x.foo or 'default-value'. But having such an operator only allowed with a property access on the right hand side seems a bit crazy (and very context sensitive)...

I suggest that we tweak it such that x.foo == null and x.foo || 'default-value' both works. This is supposed to be a simple expression language, being super explicit as is preferred in python might not be the best choice for an embedded expression language.

Escape sequences for strings in expressions

Let's say I have an expression: {$eval: " 'ab' "} with more spacing.

What kind of escape sequences should we support.

Given that json-e is usually written as JSON or YAML.
We might not need a lot of escape sequences, example: {"$eval": " 'a\nb' "}, should already work, because when you parse it as JSON/YAML \n gets interpreted...

So in order to make a string that contains ", I would have to write (as text):
{"$eval": " \"a\\\"b\" "}

Which also currently works, because \" is intepreted at json-e level... But all other escape sequences don't work at json-e level... Should we add those, or not?

Perhaps we don't want more escape sequences because you don't need them... when they are handled at JSON/YAML level... Perhaps we don't want any escape sequences, even for \\\" since it's kind of easy to get that wrong.

Thought everybody?

Fail on undefined {$operator: ..}

We should reserve all object keys named with a single $ prefix, forcing users to always write $$. Then we can introduce new operators without concern for backward compatibility.

Split demo site into three pages

As described in https://github.com/taskcluster/json-e/pull/105#pullrequestreview-45264466

Maybe split this into three pages (entrypoints): home, docs, and playground. The home page would have the header that's baked into app.js at the moment; the docs would be a faithful rendition of the full README (without special-casing certain headings), and the playground would be a cleaner view. It's a bit confusing right now that the first of 100 template/context/result rows is a playground, while the rest start with interesting content.

Add `$let`

It would be really convenient to write

{$let: {
    ts: "fromNow('100 days')",
    foo: "bar + 10",
  },
 in: [{$eval: "parseDate(ts).year"}, {$eval: "parseDate(ts).month"}, {$eval: "parseDate(ts).day"}]}

This doesn't introduce any potential for looping or recursion, but it does make the context handling a little more complicated since within the in there are additional "variables" available that are not in the global context.

Note that the let variables are not ordered, so the cannot depend on one another (that is, foo: "ts + 10" would not work).

truthyness of functions

functions are first class, we need to define truthyness, and equality... add tests for this and provide that it works...

in-operator should support deep-equality on array

{a: 45} in ["string", 46, {a: 45}] should be legal, and true..

Note: "a" in {"a": 45} is also true, I'm not sure we should allow: 5 in {"5": 45}... I suspect we don't want implicit type conversion... so I suggest we keep those semantics as is...

Implement the in-operator from python

We should implement the in operator from python... Like 3 in [1,3,4,6].
It's a very common thing to test for, and it's one less function we need in our standard library.

syntax for array access and slicing

@jonasfj -> I am thinking of this kind of syntax

var context = {key: [1,2,3,4,5]};
var template = {
a: '${ $key(0) }',
b: '${ $key(1) }',
c: {$eval: '$key(0,2)'}
};

result = {a: '1' b: '2',c: [1, 2]};

Sort numbers lexically

Numbers should sort in numeric order -- they are currently sorted lexically.

Strings should sort in lexical order -- this works now.

Sorting between the two, without a by function, can probably remain undefined (and we don't need to check for that case).

Need `exists` syntax in expression language

We may want to conditionalize something on the presence of an object property, or on the presence of a property in the context.

Depending on how we handle missing object properties, the latter might be easy. But for context properties, we will need a function. Perhaps exists(abc) and exists(abc.def), where both would fail if there is no abc in the context, and the latter would fail if abc is not an object or does not have a def property.

Define standard library (a base context with functions)

@hammad13060,

I'm thinking that json-e should have some standard library... Well, a set of functions that a built-in.
What do you think?

My thinking is things like:

  • sqrt(x) for square root
  • min/max(a,b)
  • str(x) for converting to string
  • uppercase(x)
  • lowercase(x)
  • abs(c) absolute value
  • hex(x) to hexa decimal encoding
  • floor/ceil(x)
  • len(x) length of x
  • sort(x)
  • pow(a, b)
  • parse(json)
  • stringify(json)
  • round(x)
  • sum(x) compute sum of values in x
  • codepoint(x) get integer value of character x, where x is a string of length 1

I'm not sure if we system put them under a namespace like builtin.pow or math.pow or if we should name the otherwise, or which functions we might be missing...

But we probably need things like getting the length of a list, converting integer to string. Those we can't live without. I suspect a few others like uppercase/lowercase are useful too.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.