How can I create a JSON structure dynamically from Go?
As in, serializing JSON.
My current code doesn't work, and I think it must have something to do with the fact that _Map, _String, etc. are not public.
// vim:ft=go:ts=2
package main
import "json"
import "fmt"
import vector "container/vector"
func main() {
groceries := vector.New(0);
groceries.Push(&json._String{s:"Eggs"});
groceries.Push(&json._String{s:"Bread"});
groceries.Push(&json._String{s:"Milk"});
var tree json.Json = &json._Map{m:map[string]json.Json{
"hello": &json._String{s:"world"},
"groceries": &json._Array{a:groceries}
}};
fmt.Printf(json.开发者_如何学编程JsonToString(tree));
}
Have a look at the TestJsonMap function in $GOROOT/src/pkg/json/generic_test.go, it seems to do something similar to what you want. The relevant code is
var jsontests = []string{
`null`,
`true`,
`false`,
`"abc"` // , etc.
}
values := make(map[string]Json);
mapstr := "{";
for i := 0; i < len(jsontests); i++ {
val, ok, errtok := StringToJson(jsontests[i]);
if !ok {
t.Errorf("StringToJson(%#q) => error near %v", jsontests[i], errtok)
}
if i > 0 {
mapstr += ","
}
values[jsontests[i]] = val;
mapstr += Quote(jsontests[i]);
mapstr += ":";
mapstr += JsonToString(val);
}
mapstr += "}";
mapv, ok, errtok := StringToJson(mapstr);
You want to push the value "world" onto the name "hello" and ["Eggs","Bread","Milk"] onto "Groceries". Try
var values = make(map[string]string);
values["hello"] = `"world"`;
values["groceries"] = `["Eggs","Bread","Milk"]`;
mapstr := "{";
needcomma := false;
for key,val := range values {
jsonval, ok, errtok := json.StringToJson(val);
// Check errors
// Add a comma
if needcomma == true {
mapstr += ",";
} else {
needcomma = true;
}
mapstr += json.Quote(key);
mapstr += ":";
mapstr += json.JsonToString(jsonval);
}
mapstr += "}";
mapv, ok, errtok := json.StringToJson(mapstr);
Here is the bare bones of an implementation of the interface for Json
:
package main
import {"json"; "fmt"; "os";}
type MyTest struct { MyMap map[string]string;}
func (t * MyTest) Kind() int { return json.MapKind }
func (t * MyTest) Len() int { return len (t.MyMap) }
func (t * MyTest) Number() float64 { return 0 }
func (t * MyTest) Bool() bool { return false }
func (t * MyTest) Elem(int) json.Json { return json.Null }
func (t * MyTest) String() (s string) {
s = "{";
count := 0;
for key, value := range t.MyMap {
s += json.Quote(key) + ":" + json.Quote(value);
count++;
if (count < len (t.MyMap)) {
s += ",";
}
}
s += "}";
return;
}
func (t * MyTest) Get(s string) json.Json {
j, ok, errtok := json.StringToJson (t.MyMap[s]);
if ! ok {
fmt.Printf ("Fail at %s\n", errtok);
os.Exit (1);
}
return j;
}
Here is some testing code:
func main () {
var megaburger = new (MyTest);
megaburger.MyMap = make(map[string]string);
megaburger.MyMap["frog"] = "toad";
megaburger.MyMap["captain"] = "kirk";
megaburger.MyMap["laser"] = "phaser";
fmt.Println (megaburger.Kind());
fmt.Println (megaburger.Len());
fmt.Println (json.JsonToString (megaburger));
}
This puts a JsonToString method onto the type MyTest
by defining the interface for the Json package. Clearly this doesn't do anything interesting yet, but you could define various things like these for your particular data structure in order to have a "JSON-izer" which created whatever JSON you liked from your structure. There is a nice example of how to do embedding using something called _Null
in the library source code file generic.go
.
This looks promising.
//import "github.com/Jeffail/gabs"
jsonObj := gabs.New()
// or gabs.Consume(jsonObject) to work on an existing map[string]interface{}
jsonObj.Set(10, "outter", "inner", "value")
jsonObj.SetP(20, "outter.inner.value2")
jsonObj.Set(30, "outter", "inner2", "value3")
fmt.Println(jsonObj.String())
// Prints
// {"outter":{"inner":{"value":10,"value2":20},"inner2":{"value3":30}}}
精彩评论