convert string to json in golang and vice versa?

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

convert string to json in golang and vice versa?

问题

在我的应用程序中,我从客户端接收到一个 JSON。由于用户定义了键和值,所以这个 JSON 可以是任何内容。在后端,我将其作为字符串存储在数据存储中。

现在我正在尝试重写 MarshalJson / UnmarshalJson 函数,以便我从客户端发送/接收的内容不是字符串,而是 JSON。

我无法弄清楚如何在 Go 中将字符串转换为 JSON。

我的结构如下:

type ContextData string
type Iot struct {
    Id      IotId        `json:"id,string" datastore:"-" goon:"id"`
    Name    string       `json:"name"`
    Context ContextData  `json:"context" datastore:",noindex"`
}

接收到的数据示例:

{
    "id": "",
    "name": "",
    "context": {
        "key1": "value1",
        "key2": "value2"
    }
}

我希望将这个 Context 字段作为一个非索引字符串存储在数据存储中,例如 '{"key1":value1, "key2":value2}'

要发送的数据示例:

{
    "id": "",
    "name": "",
    "context": {
        "key1": "value1",
        "key2": "value2"
    }
}
英文:

In my app, I receive a json from the client. This json can be anything since the user defines the keys and the values. In the backend I store it as string in the datastore.

Now i'm trying to override the MarshalJson / UnmarshalJson functions so that what I send / receive from the client is not a string but a json.

I can't figure out how to convert a string to json in go.

my structure

type ContextData string
type Iot struct {
Id              IotId       `json:"id,string" datastore:"-" goon:"id"`
Name            string   `json:"name"`
Context         ContextData  `json:"context" datastore:",noindex"` }

example of received data

{ 'id' : '',
  'name' '',
  'context': {
           'key1': value1,
           'key2': value2 }}

how i want to store this Context field in the datastore as a noindex string '{'key1':value1, 'key2':value2}'
example of data i want to send

{ 'id' : '',
  'name' '',
  'context': {
           'key1': value1,
           'key2': value2 }}

答案1

得分: 23

如果您没有结构化数据,但确实需要发送完整的JSON,那么可以按照以下方式读取它:

// 一个任意的JSON字符串
jsonString := "{"foo":{"baz": [1,2,3]}}"

var jsonMap map[string]interface{}
json.Unmarshal([]byte(jsonString), &jsonMap)

fmt.Println(jsonMap)
// 输出:map[foo:map[baz:[1 2 3]]]

当然,这种方法有一个很大的缺点,就是您不知道每个项的内容,因此在使用之前需要将对象的每个子项转换为其正确的类型。

// 内部项的类型为interface{}
foo := jsonMap["foo"]

// 将foo转换为正确的类型
fooMap := foo.(map[string]interface{})

// 现在我们可以使用它,但它的子项仍然是interface{}
fmt.Println(fooMap["baz"])

如果您发送的JSON可以更加结构化,那么可以简化此过程,但如果您想接受任何类型的JSON字符串,那么在使用数据之前必须检查并将其转换为正确的类型。

您可以在此播放器中找到运行代码

英文:

If you have no structured data and you really need to send a full JSON, then you can read it like this:

// an arbitrary json string
jsonString := "{\"foo\":{\"baz\": [1,2,3]}}"

var jsonMap map[string]interface{}
json.Unmarshal([]byte(jsonString ), &jsonMap)

fmt.Println(jsonMap)	
// prints: map[foo:map[baz:[1 2 3]]]

Of course, this has a big disadvantage, in that you don't know what is the content of each item, so you need to cast each of the children of the object to its proper type before using it.

// inner items are of type interface{}
foo := jsonMap["foo"]

// convert foo to the proper type
fooMap := foo.(map[string]interface{})

// now we can use it, but its children are still interface{}
fmt.Println(fooMap["baz"])

You could simplify this if the JSON you send can be more structured, but if you want to accept any kind of JSON string then you have to check everything and cast to the correct type before using the data.

You can find the code working in this playground.

答案2

得分: 7

如果我正确理解你的问题,你想将json.RawMessage作为Context使用。

RawMessage是一个原始编码的JSON对象。它实现了MarshalerUnmarshaler接口,可以用于延迟JSON解码或预先计算JSON编码。

RawMessage实际上就是[]byte,所以你可以将它保存在数据存储中,然后将其附加到出站消息中作为"预先计算的JSON"。

type Iot struct {
    Id      int             `json:"id"`
    Name    string          `json:"name"`
    Context json.RawMessage `json:"context"` // 这里使用RawMessage!(不是字符串)
}

func main() {
    in := []byte(`{"id":1,"name":"test","context":{"key1":"value1","key2":2}}`)

    var iot Iot
    err := json.Unmarshal(in, &iot)
    if err != nil {
        panic(err)
    }

    // Context是[]byte类型,所以你可以将其作为字符串保存在数据库中
    fmt.Println("ctx:", string(iot.Context))

    // 再次编码为JSON(与原始数据相同)
    out, _ := json.Marshal(&iot)
    fmt.Println(string(out))
}

链接:https://play.golang.org/p/69n0B2PNRv

英文:

If I understand your problem correctly, you want to use json.RawMessage as Context.

> RawMessage is a raw encoded JSON object. It implements Marshaler and Unmarshaler and can be used to delay JSON decoding or precompute a JSON encoding.

RawMessage is just []byte, so you can keep it in data store and then attach it for an outgoing messages as "precomputed JSON".

type Iot struct {
	Id      int             `json:"id"`
	Name    string          `json:"name"`
	Context json.RawMessage `json:"context"` // RawMessage here! (not a string)
}

func main() {
	in := []byte(`{"id":1,"name":"test","context":{"key1":"value1","key2":2}}`)

	var iot Iot
	err := json.Unmarshal(in, &iot)
	if err != nil {
		panic(err)
	}

	// Context is []byte, so you can keep it as string in DB
	fmt.Println("ctx:", string(iot.Context))

	// Marshal back to json (as original)
	out, _ := json.Marshal(&iot)
	fmt.Println(string(out))
}

https://play.golang.org/p/69n0B2PNRv

答案3

得分: 2

我不太清楚你具体想要做什么,但是在Go语言中,我知道有两种将接收到的数据转换为JSON的方法。这些数据应该是[]byte类型的。

第一种方法是允许编译器选择接口并尝试以以下方式解析为JSON:

[]byte(`{"monster":[{"basic":0,"fun":11,"count":262}],"m":"18"}`)
bufferSingleMap   map[string]interface{}
json.Unmarshal(buffer , &bufferSingleMap)

第二种方法是如果你确切地知道接收到的数据的结构,你可以先定义一个结构体:

type Datas struct{
    Monster []struct {
        Basic int     `json:"basic"`
        Fun int       `json:"fun"`
        Count int     `json:"count"`
    }                 `json:"Monster"`
    M int             `json:"m"`
}

Datas datas;
json.Unmarshal(buffer , &datas)

重要的是属性名的首字母要大写(Fun,Count),这是Unmarshal的一个标志,表示它们应该是JSON格式的。如果你仍然无法解析为JSON,请展示一下你接收到的数据,可能是它们的语法有问题。

英文:

I little also don't know what You want to do exacly, but in go I know two ways to convert some received data to json. This data should be as []byte type

first is allow to compiler choice interface and try parsed to JSON in this way:

[]byte(`{"monster":[{"basic":0,"fun":11,"count":262}],"m":"18"}`) 
bufferSingleMap   map[string]interface{}
json.Unmarshal(buffer , &bufferSingleMap)

socond if You know how exacly looks received data You can first define structure

type Datas struct{

	Monster []struct {
		Basic int     `json:"basic"`
		Fun int       `json:"fun"`
		Count int	  `json:"count"`
	}                 `json:"Monster"`
	M int             `json:"m"`
}

Datas datas;
json.Unmarshal(buffer , &datas)

Imporant is name value. Should be writed with a capital letter (Fun, Count) This is a sign for Unmarshal that should be json.
If You still don't can parsed to JSON show us Your received data, may be they have a bad syntax

huangapple
  • 本文由 发表于 2015年12月15日 22:40:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/34292012.html
匿名

发表评论

匿名网友

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

确定