Golang返回嵌套的JSON

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

Golang return nested JSON

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言,一直在尝试找出如何从"Outer"中输出原始的内部JSON数据"{"data":"Some data"}",但是到目前为止还没有成功...

这是输入数据:

{
"Outer": "{"data":"Some data"}"
}

我想要得到的是带有斜杠的以下字符串:

{"data":"Some data"}

英文:

I'm new to Go and have been trying to figure out how to output the raw inner JSON
"{"data":"Some data"}" from "Outer". So far, no luck...

This is the input data:

{
 "Outer": "{\"data\":\"Some data\"}"
}

What I would like to get is the following as a string with the slashes:

{\"data\":\"Some data\"}

答案1

得分: 3

如果你知道键("Outer"),你可以像这样做(在Playground上):

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	// 创建用于 JSON 的映射
	m := map[string]json.RawMessage{}

	// 解析 JSON
	err := json.Unmarshal([]byte(input), &m)

	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", m["Outer"])
}

const input = `
{
	"Outer": "{\"data\":\"Some data\"}"
}
`

请注意,你的示例 JSON 缺少 data 后面的最后一个转义符。如果没有它,你将会得到一个错误。

如果你不知道结构,可以参考这个回答,了解如何处理任意嵌套的数据。

英文:

If you know the key ("Outer") you can do it like this (on the Playground):

package main

import (
	"encoding/json"
	"fmt"	
)

func main() {
	//Creating the maps for JSON
	m := map[string]json.RawMessage{}

	//Parsing/Unmarshalling JSON encoding/json
	err := json.Unmarshal([]byte(input), &m)

	if err != nil {
		panic(err)
	}
	fmt.Printf("%s", m["Outer"])
}

const input = `
{
 "Outer": "{\"data\":\"Some data\"}"
}
`

Note that your example json is missing the final escape after data. Without that you'll get an error.

If you don't know your structure see this reply for how to do it with arbitrary nested data.

答案2

得分: 2

这开始只是对先前答案的评论,但逐渐扩展开来。

虽然你可以将其反序列化为临时的map[string]interface{}(或map[string]json.RawMessage),但如果有其他你只想忽略的“外部”字段,那么这可能会做很多额外的工作,而且还需要检查找到的类型(例如,对于坏/意外的输入,如{"Outer": 42})。
这可能意味着在先前的答案中添加类似以下的内容:

str, ok := m["Outer"].(string)
if !ok { return errors.New("...") }
err := json.Unmarshal([]byte(str), &actual)

更简单的方法可能是使用临时的包装类型,像这样:

var tmp struct{ Outer string }
err := json.Unmarshal(b, &tmp)
if err != nil { ... }

var data actualType
err := json.Unmarshal([]byte(tmp.Outer), &data)

你可以在一个单独的函数中执行此操作,该函数返回所需的类型(或错误),例如func foo(b []byte) (actualType, error)
或者,你可以在包装类型上的自定义UnmarshalJSON方法中放入这个变体,以实现json.Unmarshaler
如果你想能够以相同的格式进行编组,也可以执行相反的操作。

在playground上有完整的可运行示例:https://play.golang.org/p/IXU2koyJ1A

英文:

This started out as just a comment on a previous answer but grew.

Although you can unmarshal into a temporary map[string]interface{} (or map[string]json.RawMessage) that can do a lot of extra work if there are other "outer" fields that you just want to ignore and it also requires checking the type that was found
(e.g. for the case of bad/unexpected input like {"Outer": 42}).
That probably means adding something like this to the previous answer:

    str, ok := m["Outer"].(string)
    if !ok { return errors.New("…") }
    err := json.Unmarshal([]byte(str), &actual)

Much simpler is probably to use a temporary wrapping type like so:

    var tmp struct{ Outer string }
    err := json.Unmarshal(b, &tmp)
    if err != nil { … }

    var data actualType
    err := json.Unmarshal([]byte(tmp.Outer), &data)

You could either do this in a separate function that returns the type you wanted (or an error, e.g. func foo(b []byte) (actualType, error)).
Or you could put a variation of this into a custom UnmarshalJSON method on a wrapper type so as to implement json.Unmarshaler.
You could also do the reverse if you wanted to be able to marshal back into the same format.

Full runnable examples on the playground: https://play.golang.org/p/IXU2koyJ1A

huangapple
  • 本文由 发表于 2015年4月30日 16:19:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/29962542.html
匿名

发表评论

匿名网友

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

确定