GithubHelp home page GithubHelp logo

qri-io / jsonpointer Goto Github PK

View Code? Open in Web Editor NEW
16.0 3.0 3.0 15 KB

golang implementation of IETF RFC6901: https://tools.ietf.org/html/rfc6901

License: MIT License

Shell 1.55% Go 97.42% Makefile 1.03%
golang ietf json

jsonpointer's Introduction

Qri GoDoc License Codecov CI Go Report Card

jsonpointer

golang implementation of IETF RFC6901: JSON Pointer defines a string syntax for identifying a specific value within a JavaScript Object Notation (JSON) document.

Installation

install with: go get -u github.com/qri-io/jsonpointer

Usage

Here's a quick example pulled from the godoc:

import (
  "encoding/json"
  "fmt"
  "github.com/qri-io/jsonpointer"
)

var document = []byte(`{ 
  "foo": {
    "bar": {
      "baz": [0,"hello!"]
    }
  }
}`)

func main() {
  parsed := map[string]interface{}{}
  // be sure to handle errors in real-world code!
  json.Unmarshal(document, &parsed)

  // parse a json pointer. Pointers can also be url fragments
  // the following are equivelent pointers:
  // "/foo/bar/baz/1"
  // "#/foo/bar/baz/1"
  // "http://example.com/document.json#/foo/bar/baz/1"
  ptr, _ := jsonpointer.Parse("/foo/bar/baz/1")

  // evaluate the pointer against the document
  // evaluation always starts at the root of the document
  got, _ := ptr.Eval(parsed)

  fmt.Println(got)
  // Output: hello!
}

License

MIT

Issues & Contributions

Contributions & Issues are more than welcome! Everything happens over on this repo's github page

jsonpointer's People

Contributors

arqu avatar b5 avatar osterbit avatar ramfox avatar

Stargazers

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

Watchers

 avatar  avatar  avatar

jsonpointer's Issues

Ability to modify value in a document using Pointer

Hello there,

Thank you for such clean and simple library!

What feature or capability would you like?

I'd like to have an ability to have a call like pointer.Set(interface{}). E.g., if we treat pointer.Eval() as Get method, it would be great to have a Set version as well.

Do you have a proposed solution?

Yes, probably some recursive (or just a bit more if-hairy iteration) over pointer parts -- we should be aware of the latest part in the pointer and set its value in a document instead of accessing it.

Have you considered any alternative solutions or workarounds?

Yes.

Interface for travsersing json pointers in go types

In order to make json schema references work, we need an interface for traversing json pointers in decoded go types. I've seen this pattern pop up in a few places, and would love to think about how to broaden the applicability of such an interface(s).

Problem

Let's say we decode this json to a generic map[string]interface{}:

{
    "foo" : ["bar"],
    "references": {
        "a": {"$ref": "#/foo/0"},
        "b": {"$ref": "/foo/0"}
    }
}

According to the json pointer spec, Both "a" and "b" in the above example should resolve to "bar". By decoding to map[string]interface{}, this is no problem, and the current jsonpointer.Eval can handle this for you using a type switch. This breaks, however, when anything that isn't map[string]interface{} or []interface{} are provided to jsonpointer.Eval. This problem gets worse when we do exotic things with go types.

After experimenting a bunch with the "just marshal back to generic structs & traverse", it's just way too much overhead and complexity. So:

We need an interface that lets go types declare how to traverse json pointer paths

Suggested Solution:

Instead of having go structs be in charge of resolving full paths, I think each struct should only be in charge of resolving it's immediate children (if any). There are only two "container" types in JSON: objects and arrays. The thornier of the two types is an object. So I'm suggesting two interfaces.

The first interface provides fast lookup for traversing expected paths (eg, json pointers):

// JSONContainer returns any existing child value for a given JSON property string
type JSONContainer interface {
    // JSONProp takes a string reference for a given JSON property.
    // implementations must return any matching property of that name,
    // nil if no such subproperty exists.
    // Note that implementations on slice-types are expected to convert
    // prop to an integer value 
    JSONProp(prop string) interface{}
}

The second interface provides comprehensive child listing for full-tree traversal:

// JSONParent is an interface that enables tree traversal by listing
// all immediate children of an object
type JSONParent interface {
    // JSONChildren should return all immidiate children of this element
    // with json property names as keys, go types as values
    // Note that implementations on slice-types are expected to convert
    // integers to string keys
    JSONProps() map[string]interface{}
}

Looking up a path should be done by breaking up the pointer into tokens and evaluating the components, as the current jsonpointer.Eval() does, but now with a check for the JSONContainer interface, and reflection as a fallback.

The work of traversing the entire tree should be a generic function:

// WalkJSON calls visit on all elements in a tree of decoded json
jsonpointer.WalkJSON(tree interface{}, visit func(elem interface{}) error) error

This follows the spirit of encoding/json and filepath.Walk from the standard lib.
The filepath.Walk() part allows users to BYO visit function to call on each element in a tree.

Both functions would follow the spirit of the way encoding/json handles mapping JSON to go types:

  • Checks for implementation of the above interfaces, using those if present.
  • Has fast-paths for map[string]interface{} and []interface{}
  • Falls back reflection, examining the json tag when present for property naming, and case-insensitive matching on exported field names otherwise

My expectation is that most implementations on slice-types would not use the JSONContainer or JSONParent at all, and instead rely on reflection. Slice-types would still have the JSONContainer interface for odd circumstances or edge cases.

@Stebalien, I'd love to see if we can't make the distance between resolving json pointers and IPLD paths as short as possible, and would love your (or really anyone from the IPLD project's) input on this interface as we go forward. I'm assuming IPLD's needs will be a superset of these problems, but it'd be great if the two could play nicely.

I've come across this problem a bunch in the wild, and would love other's feedback on the subject. Thanks!

Provide a setter

What about providing a setter method on pointer ?
Today, only a getter (Eval) is available :)

JSONParent interface doesn't match it's documentation, nor is useful with jsonschema.Schema

Issue

I'm trying to traverse a *jsonschema.Schema using this library and notice that this library declares the following interface:

// JSONParent is an interface that enables tree traversal by listing
// all immediate children of an object
type JSONParent interface {
	// JSONChildren should return all immidiate children of this element
	// with json property names as keys, go types as values
	// Note that implementations on slice-types are expected to convert
	// integers to string keys
	JSONProps() map[string]interface{}
}

Note that the JSONProps() function is actually documented as JSONChildren.

Also, https://github.com/qri-io/jsonschema exposes the JSONChildren() function and not JSONProps().

Do you have a suggested fix?

Two options:

  1. Don't introduce breaking changes and update the documentation here. Then update the jsonschema package to implement both JSONProps() and JSONChildren() (which implements the same behaviour)
  2. Make a breaking change to this repo and change the signature to match the documentation. The only change to jsonschema would be to update go.mod with the latest version.

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.