github.com/ndau/noms@v1.0.5/go/util/json/from_json.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package json 6 7 import ( 8 "encoding/json" 9 "io" 10 "reflect" 11 12 "github.com/ndau/noms/go/d" 13 "github.com/ndau/noms/go/types" 14 ) 15 16 func nomsValueFromDecodedJSONBase(vrw types.ValueReadWriter, o interface{}, useStruct bool) types.Value { 17 switch o := o.(type) { 18 case string: 19 return types.String(o) 20 case bool: 21 return types.Bool(o) 22 case float64: 23 return types.Number(o) 24 case nil: 25 return nil 26 case []interface{}: 27 items := make([]types.Value, 0, len(o)) 28 for _, v := range o { 29 nv := nomsValueFromDecodedJSONBase(vrw, v, useStruct) 30 if nv != nil { 31 items = append(items, nv) 32 } 33 } 34 return types.NewList(vrw, items...) 35 case map[string]interface{}: 36 var v types.Value 37 if useStruct { 38 structName := "" 39 fields := make(types.StructData, len(o)) 40 for k, v := range o { 41 nv := nomsValueFromDecodedJSONBase(vrw, v, useStruct) 42 if nv != nil { 43 k := types.EscapeStructField(k) 44 fields[k] = nv 45 } 46 } 47 v = types.NewStruct(structName, fields) 48 } else { 49 kv := make([]types.Value, 0, len(o)*2) 50 for k, v := range o { 51 nv := nomsValueFromDecodedJSONBase(vrw, v, useStruct) 52 if nv != nil { 53 kv = append(kv, types.String(k), nv) 54 } 55 } 56 v = types.NewMap(vrw, kv...) 57 } 58 return v 59 60 default: 61 d.Chk.Fail("Nomsification failed.", "I don't understand %+v, which is of type %s!\n", o, reflect.TypeOf(o).String()) 62 } 63 return nil 64 } 65 66 // NomsValueFromDecodedJSON takes a generic Go interface{} and recursively 67 // tries to resolve the types within so that it can build up and return 68 // a Noms Value with the same structure. 69 // 70 // Currently, the only types supported are the Go versions of legal JSON types: 71 // Primitives: 72 // - float64 73 // - bool 74 // - string 75 // - nil 76 // 77 // Composites: 78 // - []interface{} 79 // - map[string]interface{} 80 func NomsValueFromDecodedJSON(vrw types.ValueReadWriter, o interface{}, useStruct bool) types.Value { 81 return nomsValueFromDecodedJSONBase(vrw, o, useStruct) 82 } 83 84 func FromJSON(r io.Reader, vrw types.ValueReadWriter, opts FromOptions) (types.Value, error) { 85 dec := json.NewDecoder(r) 86 // TODO: This is pretty inefficient. It would be better to parse the JSON directly into Noms values, 87 // rather than going through a pile of Go interfaces. 88 var pile interface{} 89 err := dec.Decode(&pile) 90 if err != nil { 91 return nil, err 92 } 93 return NomsValueFromDecodedJSON(vrw, pile, opts.Structs), nil 94 } 95 96 // FromOptions controls how FromJSON works. 97 type FromOptions struct { 98 // If true, JSON objects are decoded into Noms Structs. Otherwise, they are decoded into Maps. 99 Structs bool 100 }