jsonpointer - an RFC 6901 implementation for Go

jsonpointer - an RFC 6901 implementation for Go

Package jsonpointer provides the ability to resolve, assign, and delete values of any type, including raw JSON, by JSON Pointers.

GoDoc

Motivation

jsonpointer was built to support github.com/chanced/openapi but it may be useful for others so it has been released as an independent package.

For the openapi package, I needed a way to resolve and assign JSON Pointers against concrete types while also maintaining integrity of pointer values. All existing JSON Pointer implementations for Go operate on map[string]interface{} and []interface{}, raw JSON, or both.

Install

go get github.com/chanced/jsonpointer

Usage

General

package main

import (
    "log"
    "encoding/json"
    "github.com/chanced/jsonpointer"
)

type Nested struct {
    Str string
}

type Root struct {
    Nested Nested
}

func main() {

    r := Root{ Nested: Nested{ Str: "nested str" }}

    // jsonpointer.JSONPointer is a string type so if you have a properly
    // formatted json pointer then you can simply convert it:
    //  ptr := jsonpointer.JSONPointer(myPointer)
    //  err := ptr.Validate()

    // Note: jsonpointer.New encodes each token's value.
    // "/" encodes to "~1" and "~" encodes to "~0" in compliance with RFC 6901.

    ptr := jsonpointer.New("nested", "str")

    // Resolve

    var s string
    err := jsonpointer.Resolve(r, ptr, &s)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(s) // outputs "nested str"

    // Assign

    err = jsonpointer.Assign(&r, ptr, "new value")
    if err != nil {
        log.Fatal(err)
    }
    log.Println(r.Nested.Str) // outputs "new value"


    // Delete

    err = jsonpointer.Delete(&r, ptr)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(r.Nested.Str) // outputs ""


    // jsonpointer can also Resolve, Assign, and Delete JSON in []byte format.
    // This includes field values, such as those of type json.RawMessage.

    r.Nested.Str = "str val"

    b, err := json.Marshal(r)
    if err != nil {
        log.Fatal(err)
    }

    err = jsonpointer.Resolve(b, ptr, &s)
    if err != nil {
        log.Fatal(err)
    }
    log.Println(s) // outputs "str val"
}

Interfaces

Package jsonpointer provides 3 interfaces: Assigner, Resolver, and Deleter. Regardless of the operation, if Resolver is implemented, ResolveJSONPointer will be called. ResolveJSONPointer should not have side effects. If resolving for an assignment, utilize the pointer to infer which type should be assigned.

AssignByJSONPointer is invoked on the way back from the leaf. DeleteByJSONPointer is invoked after resolving the current token.

All three methods are passed a pointer to the jsonpointer.JSONPointer so that it can be modified. If you do not modify it, jsonpointer will assume the current token was addressed and continue on.

If you wish to only handle some cases with the interfaces, return jsonpointer.YieldOperation to have the jsonpointer package resolve, assign, or delete as if the type did not implement the interface. Note that doing so results in changes to ptr being dismissed.

JSONPointer methods

All methods return new values rather than modifying the pointer itself. If you wish to modify the pointer in one of the interface methods, you will need to reassign it: *ptr = newPtrVal

func (mt MyType) ResolveJSONPointer(ptr *jsonpointer.JSONPointer, op Operation) (interface{}, error) {
    next, t, ok := ptr.Next()
    if !ok {
        // this will only occur if the ptr is a root token in this circumstance
        return mt
    }
    if op == jsonpointer.Assigning && t == "someInterface" {
        // maybe you need to know what comes after someInterface to
        // determine what implementation of someInterface to assign
        t, _ = next.NextToken()

        switch t {
        case "someIdentifier":
            // you could modify ptr if you felt so inclined: *ptr = next
            // but it is not needed in this scenario.
            return SomeImplementation{}, nil
        }
    }
    // otherwise hand resolution back over to jsonpointer
    return nil, jsonpointer.YieldOperation
}

Errors

All errors returned from Resolve, Assign, and Delete will implement Error. A convenience function AsError exists to help extract out the details.

Depending on the cause, the error could also be KeyError, IndexError, FieldError with additional details. All have corresponding As{Error} functions.

Finally, all errors have associated Err instances that are wrapped, such as ErrMalformedToken, ErrInvalidKeyType, and so on.

See errors.go for further details on errors.

Contributions & Issues

Contributions are always welcome. If you run into an issue, please open a issue on github. If you would like to submit a change, feel free to open up a pull request.

Note on Performance

This package is reflect heavy. While it employs the same caching mechanics as encoding/json to help alleviate some of the lookup costs, there will always be a performance hit with reflection.

There are also probably plenty of ways to improve performance of the package. Improvements or criticisms are always welcome.

With regards to raw JSON, json.Marshal and json.Unmarshal are utilized. Ideally, in the future, that will change and the package will incoroprate the encoding/decoding logic from encoding/json directly, thus skipping the need to run through unneccesary logic.

Alternative JSON Pointer Packages for Go

License

Apache 2.0

Similar Resources

Implements the XDR standard as specified in RFC 4506 in pure Go (Golang)

go-xdr [] (https://travis-ci.org/davecgh/go-xdr) [![Coverage Status] (https://coveralls.io/repos/davecgh/go-xdr/badge.png?branch=master)] (https://cov

Dec 15, 2022

Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed.

arp Package arp implements the ARP protocol, as described in RFC 826. MIT Licensed. Portions of this code are taken from the Go standard library. The

Dec 20, 2022

CoAP Client/Server implementing RFC 7252 for the Go Language

Canopus Canopus is a client/server implementation of the Constrained Application Protocol (CoAP) Updates 25.11.2016 I've added basic dTLS Support base

Nov 18, 2022

Package dhcp6 implements a DHCPv6 server, as described in RFC 3315. MIT Licensed.

dhcp6 Package dhcp6 implements a DHCPv6 server, as described in IETF RFC 3315. MIT Licensed. At this time, the API is not stable, and may change over

Sep 27, 2022

Diameter stack and Base Protocol (RFC 6733) for the Go programming language

Diameter Base Protocol Package go-diameter is an implementation of the Diameter Base Protocol RFC 6733 and a stack for the Go programming language. St

Dec 28, 2022

URI Templates (RFC 6570) implemented in Go

uritemplates -- import "github.com/jtacoma/uritemplates" Package uritemplates is a level 4 implementation of RFC 6570 (URI Template, http://tools.ietf

Jan 15, 2022

CBOR RFC 7049 (Go/Golang) - safe & fast with standard API + toarray & keyasint, CBOR tags, float64/32/16, fuzz tested.

CBOR RFC 7049 (Go/Golang) - safe & fast with standard API + toarray & keyasint, CBOR tags, float64/32/16, fuzz tested.

CBOR library in Go fxamacker/cbor is a CBOR encoder & decoder in Go. It has a standard API, CBOR tags, options for duplicate map keys, float64→32→16,

Jan 6, 2023

Go package for UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.

uuid The uuid package generates and inspects UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services. This package is based on the g

Jan 1, 2023

Package json implements encoding and decoding of JSON as defined in RFC 7159

Package json implements encoding and decoding of JSON as defined in RFC 7159. The mapping between JSON and Go values is described in the documentation for the Marshal and Unmarshal functions

Jun 26, 2022

A commandline tool to resolve URI Templates expressions as specified in RFC 6570.

URI Are you tired to build, concat, replace URL(s) (via shell scripts sed/awk/tr) from your awesome commandline pipeline? Well! here is the missing pi

Jun 9, 2021

A simple uuid library based on RFC 4122

UUID generator A simple library that generates uuids. Supported versions: version 1 version 3 version 4 version 5 Supported variants: DCE Microsoft Th

Oct 20, 2021

RFC 1413 compliant fake identd

RFC 1413 compliant fake identd. It is an implementation of the Ident Protocol, but it lies to the clients and always returns fake identities of queried users.

Oct 29, 2022

Parse a RFC 3339 duration string into time.Duration

duration Parse a RFC3339 duration string into time.Duration There are probably a few unsupported edge cases still to be fixed, please help me find the

Nov 25, 2021

Rabbitio - Rabbit stream cipher package RFC 4503 for Go

rabbitio rabbitio is a rabbit stream cipher packge based on RFC 4503 for golang

Dec 14, 2022

Go language implementation of a blockchain based on the BDLS BFT protocol. The implementation was adapted from Ethereum and Sperax implementation

BDLS protocol based PoS Blockchain Most functionalities of this client is similar to the Ethereum golang implementation. If you do not find your quest

Oct 14, 2022

CVE-2021-4034 - A Golang implementation of clubby789's implementation of CVE-2021-4034

CVE-2021-4034 January 25, 2022 | An00bRektn This is a golang implementation of C

Feb 3, 2022

An implementation of JOSE standards (JWE, JWS, JWT) in Go

Go JOSE Package jose aims to provide an implementation of the Javascript Object Signing and Encryption set of standards. This includes support for JSO

Dec 18, 2022

goRBAC provides a lightweight role-based access control (RBAC) implementation in Golang.

goRBAC goRBAC provides a lightweight role-based access control implementation in Golang. For the purposes of this package: * an identity has one or mo

Dec 29, 2022

This is an implementation of JWT in golang!

jwt This is a minimal implementation of JWT designed with simplicity in mind. What is JWT? Jwt is a signed JSON object used for claims based authentic

Oct 25, 2022
Comments
  • Add interfaces that pass in context. Also add WithContext as an option to all operations.

    Add interfaces that pass in context. Also add WithContext as an option to all operations.

    Add interfaces that pass in context. Also add WithContext as an option to all operations to further assist with determining what ResolveJSONPointer should return.

Pure Go implementation of jq

gojq Pure Go implementation of jq This is an implementation of jq command written in Go language. You can also embed gojq as a library to your Go prod

Jan 9, 2023
This an implementation of Jsonnet in pure Go.

This an implementation of Jsonnet in pure Go. It is a feature complete, production-ready implementation. It is compatible with the original Jsonnet C++ implementation. Bindings to C and Python are available (but not battle-tested yet).

Dec 29, 2022
COBS implementation in Go (Decoder) and C (Encoder & Decoder) with tests.

COBS Table of Contents About The project COBS Specification Getting Started 3.1. Prerequisites 3.2. Installation 3.3. Roadmap Contributing License Con

May 22, 2022
Oct 8, 2022
A go implementation of the STUN client (RFC 3489 and RFC 5389)

go-stun go-stun is a STUN (RFC 3489, 5389) client implementation in golang (a.k.a. UDP hole punching). RFC 3489: STUN - Simple Traversal of User Datag

Jan 5, 2023
Fast RFC 5389 STUN implementation in go

STUN Package stun implements Session Traversal Utilities for NAT (STUN) [RFC5389] protocol and client with no external dependencies and zero allocatio

Nov 28, 2022
RFC 4566 SDP implementation in go

SDP Package sdp implements SDP: Session Description Protocol [RFC4566]. Complies to gortc principles as core package. Examples See examples folder. Al

Nov 9, 2022
Fast RFC 5389 STUN implementation in go

STUN Package stun implements Session Traversal Utilities for NAT (STUN) [RFC5389] protocol and client with no external dependencies and zero allocatio

Jan 1, 2023
Implementation of RFC-6238 (Time-Based One-Time Password Algorithm) in Go.

TOTP TOTP (RFC-6238) implementation in Go with no external dependencies. INSTALL You can do little copying the totp.go file or add this package as Go

Jan 18, 2022
Sieve email filtering language (RFC 5228) implementation in Go.

go-sieve Sieve email filtering language (RFC 5228) implementation in Go.

Sep 29, 2022