2009-11-15 116 views
1

正如序列化JSON。如何從Go動態創建JSON結構?

我目前的代碼不起作用,我認爲它必須與_Map,_String等不公開的事實有關。

// 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)); 
} 
+0

您是否檢查過http://golang.org/pkg/json/上的文檔?下劃線的標識符不會被導出。 – 2009-11-15 10:35:12

+0

@devyn - 高亮語法基於固定編碼標準,可能是C#和Java的聯合。 – mauris 2009-11-15 10:42:17

+0

請記住班級是如何命名的?大寫字母先走。 – mauris 2009-11-15 10:42:48

回答

2

看一看在$ GOROOT的TestJsonMap功能/ src目錄/包裝/ JSON/generic_test.go,似乎做類似你想要什麼東西。相關的代碼是

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); 

你想要的價值「世界」推到了名爲「你好」和[「雞蛋」,「麪包」,「牛奶」]在「雜貨店」。嘗試

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); 
+0

Scott,首先這是JSON包的一部分,所以它不會在沒有改動的情況下編譯。其次,它似乎在考慮字符串並測試解析器。我不認爲這是原始海報所要求的。 devyn似乎想從數據結構創建JSON。 – 2009-11-15 11:23:28

+0

我添加了一個如何使用該片段的示例。如果需要的話,可以使用[]字符串輕鬆構建雜貨數組。 – 2009-11-15 11:41:30

+0

非常有趣,但我真正想做的是完全動態創建一個JSON字符串,例如對於JSON-RPC服務器? – devyn 2009-11-15 21:17:42

1

這裏是接口的實現的梗概爲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; 
} 

下面是一些測試代碼:

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)); 
} 

這使得一個JsonToString方法到型通過定義Json包的接口,可以獲得MyTest。很明顯,這並沒有做任何有趣的事情,但是你可以爲你的特定數據結構定義各種類似的東西,以便擁有一個「JSON-iizer」,它創建你所喜歡的JSON。在庫源代碼文件generic.go中使用_Null這種方法做了embedding的一個很好的例子。

1

This看起來很有希望。

//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}}}