go "encoding/json" : marshal json field

huangapple go评论78阅读模式
英文:

go "encoding/json" : marshal json field

问题

我有一个带有json字段(DisplayInfo和FormatInfo)的PostgreSQL模式。这些字段的结构是动态的。

我只能将其读取和呈现为字符串(在呈现结构中的字符串类型):

[
  {
    "ID": 9,
    "Name": "120 №1",
    "DisplayInfo": "{\"path\": \"http://path/to/img.png\"}",
    "Format": {
      "Code": "frame-120",
      "Width": 120,
      "Height": 60,
      "FormatInfo": "[{\"name\": \"\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\", \"field_type\": \"img\", \"key\": \"path\"}]"
    },
    "Weight": 0.075,
    "Application": 8,
    "Url": "//path/to/game",
    "Referrer": ""
  }
]

但我希望将DisplayInfo字段输出为JSON对象。怎么做?

我的呈现代码:

func renderJSON(w http.ResponseWriter, obj models.Model) {
    js, err := json.Marshal(obj)

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Write(js)
}

更新1:这些字段的结构是动态的。DisplayInfo可能有一个"path"字段,也可能没有。它们可能有额外的字段。

更新2:我想将DisplayInfo和FormatInfo作为JSON对象(而不是字符串)输出,作为整个对象的一部分,像这样:

[
  {
    "ID": 9,
    "Name": "120 №1",
    "DisplayInfo": {"path": "http://path/to/img.png"},
    "Format": {
      "Code": "frame-120",
      "Width": 120,
      "Height": 60,
      "FormatInfo": [{"name": "\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", "field_type": "img", "key": "path"}]
    },
    "Weight": 0.075,
    "Application": 8,
    "Url": "//path/to/game",
    "Referrer": ""
  }
]

更新3:结构

实际结构是:

type BannerSerializer struct {
    ID          int
    Name        string
    DisplayInfo string
    Format      formatSerializer
    Weight      float32
    Application int
    Url         string
    Referrer    string
}

然后我尝试了这个结构:

type BannerSerializer struct {
    ID          int
    Name        string
    DisplayInfo json.RawMessage
    Format      formatSerializer
    Weight      float32
    Application int
    Url         string
    Referrer    string
}
  • DisplayInfo序列化为base64字符串(或类似base64的形式,不确定)。
英文:

I have a PostgreSQL schema with json field's (DisplayInfo, and FormatInfo). Structure of this field's is dynamic.

I'can read and render it only as string (string type in render struct) :

[
 {  
  "ID":9,
  "Name":"120 №1",
  "DisplayInfo":"{\"path\": \"http://path/to/img.png\"}",
  "Format":{  
     "Code":"frame-120",
     "Width":120,
     "Height":60,
     "FormatInfo":"[{\"name\": \"\\u0413\\u043b\\u0430\\u0432\\u043d\\u043e\\u0435 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0435\", \"field_type\": \"img\", \"key\": \"path\"}]"
  },
  "Weight":0.075,
  "Application":8,
  "Url":"//path/to/game",
  "Referrer":""
 }
]

but i want output field DisplayInfo as JSON object. How ?

My render code:

func renderJSON(w http.ResponseWriter, obj models.Model) {
    js, err := json.Marshal(obj)

    if err != nil {
	    http.Error(w, err.Error(), http.StatusInternalServerError)
	    return
    }
    w.Header().Set("Content-Type", "application/json; charset=utf-8")
    w.Header().Set("Access-Control-Allow-Origin", "*")
    w.Write(js)
}

UPD 1 : Structure of this field's is dynamic. DisplayInfo may have 'path' field, or may not. They may have additional fields.

UPD 2. I wana output DisplayInfo and FormatInfo as json-object(not string), as part of whole object, like this:

[
 {  
  "ID":9,
  "Name":"120 №1",
  "DisplayInfo":{"path": "http://path/to/img.png"},
  "Format":{  
     "Code":"frame-120",
     "Width":120,
     "Height":60,
     "FormatInfo":[{"name": "\\u0413\\u043b\\u0430\\u0432\\u043d\\u043e\\u0435 \\u0438\\u0437\\u043e\\u0431\\u0440\\u0430\\u0436\\u0435\\u043d\\u0438\\u0435", "field_type": "img", "key": "path"}]
  },
  "Weight":0.075,
  "Application":8,
  "Url":"//path/to/game",
  "Referrer":""
 }
]

UPD 3: Structures

Actual structure is :

type BannerSerializer struct {
    ID          int
    Name        string
    DisplayInfo string
    Format      formatSerializer
    Weight      float32
    Application int
    Url         string
    Referrer    string
}  

Then i trying this structure:

type BannerSerializer struct {
    ID          int
    Name        string
    DisplayInfo json.RawMessage
    Format      formatSerializer
    Weight      float32
    Application int
    Url         string
    Referrer    string
}   
  • DisplayInfo serialize as base64 string (or like base64, don't know)

答案1

得分: 2

使用指向json.RawMessage的指针:

type Data struct {
    Obj *json.RawMessage
}

Playground: http://play.golang.org/p/Qq9IUBDLzJ.

英文:

Use a pointer to json.RawMessage:

type Data struct {
	Obj *json.RawMessage
}

Playground: http://play.golang.org/p/Qq9IUBDLzJ.

答案2

得分: 1

假设您可以访问更改models.Model,您可以创建自己的类型,并使用自定义的Unmarshaler返回原始字符串:

type JSONString string

func (s JSONString) MarshalJSON() ([]byte, error) {
    return []byte(s), nil
}

工作示例:

package main

import (
    "encoding/json"
    "fmt"
)

type JSONString string

func (s JSONString) MarshalJSON() ([]byte, error) {
    return []byte(s), nil
}

type Model struct {
    ID          int
    Name        string
    DisplayInfo JSONString
}

func main() {
    data := []byte(`{    
    "ID":9,
    "Name":"120 №1",
    "DisplayInfo":"{\"path\": \"http://path/to/img.png\"}"
}`)

    var obj Model
    err := json.Unmarshal(data, &obj)
    if err != nil {
        panic(err)
    }

    // 这里是您的代码
    js, err := json.Marshal(obj)

    if err != nil {
        panic(err)
    }

    fmt.Println(string(js))
}

输出:

{ "ID":9,"Name":"120 №1","DisplayInfo":{"path":"http://path/to/img.png"}}

Playground: http://play.golang.org/p/6bcnuGjlU8

英文:

Assuming you have access to change models.Model, you can create your own type with a custom Unmarshaler that just returns the raw string:

type JSONString string

func (s JSONString) MarshalJSON() ([]byte, error) {
	return []byte(s), nil
}

Working example:

package main

import (
	"encoding/json"
	"fmt"
)

type JSONString string

func (s JSONString) MarshalJSON() ([]byte, error) {
	return []byte(s), nil
}

type Model struct {
	ID          int
	Name        string
	DisplayInfo JSONString
}

func main() {
	data := []byte(`{	
  "ID":9,
  "Name":"120 №1",
  "DisplayInfo":"{\"path\": \"http://path/to/img.png\"}"
}`)

	var obj Model
	err := json.Unmarshal(data, &obj)
	if err != nil {
		panic(err)
	}

	// Here comes your code
	js, err := json.Marshal(obj)

	if err != nil {
		panic(err)
	}

	fmt.Println(string(js))
}

Output:
>{"ID":9,"Name":"120 №1","DisplayInfo":{"path":"http://path/to/img.png"}}

Playground: http://play.golang.org/p/6bcnuGjlU8

答案3

得分: 0

你需要对其进行解组,这里是一个示例:

var data []*struct {
    ID          int
    DisplayInfo string
}
if err := json.Unmarshal([]byte(j), &data); err != nil {
    log.Fatal(err)
}
for _, d := range data {
    var displayInfo struct{ Path string }
    if err := json.Unmarshal([]byte(d.DisplayInfo), &displayInfo); err != nil {
        log.Fatal(err)
    }
    fmt.Println(d.ID, displayInfo.Path)
}

playground

英文:

You'd have to unmarshal it, here's an example:

var data []*struct {
	ID int
	DisplayInfo string
}
if err := json.Unmarshal([]byte(j), &data); err != nil {
	log.Fatal(err)
}
for _, d := range data {
	var displayInfo struct{ Path string }
	if err := json.Unmarshal([]byte(d.DisplayInfo), &displayInfo); err != nil {
		log.Fatal(err)
	}
	fmt.Println(d.ID, displayInfo.Path)
}

<kbd>playground</kbd>

huangapple
  • 本文由 发表于 2015年8月5日 12:41:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/31823580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定