francoispqt / gojay

high performance JSON encoder/decoder with stream API for Golang
MIT License
2.11k stars 112 forks source link

Decode map[string]interface{}? #110

Closed Valve closed 5 years ago

Valve commented 5 years ago

Is there a way to decode arbitrary objects as a map[string]interface{}?

It should be possible to decode any object with any keys/value structure (including deeply nested objects) (as stdlib JSON package allows).

If it's currently possible, I wasn't able to find an example in the readme, could you please let me know how it's done

Valve commented 5 years ago

Ok, I figured out how to do it. It was straightforward. Below is a working example. @francoispqt one suggestion: please update readme for map[..].. examples to tell that map will not be created and you need to make it first, otherwise it will panic on a nil map insertion.

package main

import (
    "fmt"
    "strings"

    "github.com/francoispqt/gojay"
)

type Tag map[string]interface{}

func (t *Tag) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
    var value interface{}
    if err := dec.Interface(&value); err != nil {
        return err
    }
    (*t)[key] = value
    return nil
}
func (t *Tag) NKeys() int {
    return 0
}

type Container struct {
    Tag Tag
}

func (c *Container) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
    if key == "tag" {
        return dec.DecodeObject(&c.Tag)
    }
    return nil
}
func (c *Container) NKeys() int {
    return 0
}

func main() {
    json := `
    {
        "tag": {
            "age": 27,
            "requestId": {
                "foo": "bar",
                "pi": 3.14,
                "nested": {"baz": false}
            }
        }
    }
    `

    reader := strings.NewReader(json)
    decoder := gojay.NewDecoder(reader)
        // IMPORTANT!: make sure you make any maps first, otherwise it will panic.
    c := &Container{Tag: make(map[string]interface{})}
    decoder.DecodeObject(c)
    fmt.Printf("%+v\n", c)
        // &{Tag:map[age:27 requestId:map[foo:bar nested:map[baz:false] pi:3.14]]}
}
zorro786 commented 3 years ago

@francoispqt I would like to submit a fix for this. User shouldn't worry about creation of maps. Could you provide some pointers?