fastjson icon indicating copy to clipboard operation
fastjson copied to clipboard

Parse into map[string]interface

Open estutzenberger opened this issue 7 years ago • 1 comments

Hi. I like the looks of this library and I'm trying to work out from the API and examples how I can Parse an arbitrary blob of JSON into a map[string]interface{}. Is this possible?

For the development I am working on, I have to Parse JSON where the keys are unknown to the parsing code. The map is then given to a function pointer (essentially) which does know the keys.

If it is possible, I do not want to have to pass objects or structures from fastjson in order to keep dependencies at a minimum.

Thanks!

estutzenberger avatar Jan 29 '19 17:01 estutzenberger

It is possible to parse JSON by fastjson into a map[string]interface, but it has little sense, since:

  • it will allocate a lot in general case, so the performance will be similar to encoding/json.Unmarshal(map[string]interface{})
  • the solution for general case is a way complex. It will look like the following code (untested):
func ParseIntoEmptyIface(s string) (map[string]interface{}, error) {
    v, err := fastjson.Parse(s)
    if err != nil {
        return nil, err
    }
    return wrapIntoEmptyInterface(v)
}

func wrapIntoEmptyInterface(v *fastjson.Value) interface{} {
    switch v.Type() {
    case fastjson.TypeObject:
        m := make(map[string]interface{})
        v.GetObject().Visit(func(k []byte, v *fastjson.Value) {
            m[k] = wrapIntoEmptyInterface(v)
        })
        return m
    case fastjson.TypeArray:
        var a []interface{}
        for _, v := range v.GetArray() {
            a = append(a, wrapIntoEmptyInterface(v))
        }
        return a
    case fastjson.TypeString:
        return string(v.GetStringBytes())
    case fastjson.TypeTrue, fastjson.TypeFalse:
        return v.GetBool()
    default:
        return nil
}

This defeats the main purpose of fastjson - fast parsing with zero allocations

valyala avatar Feb 02 '19 21:02 valyala