在golang中对没有结构的JSON数据进行最小修改。

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

Making minimal modification to JSON data without a structure in golang

问题

我有一个以JSON格式的solr响应,看起来像这样:

{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "q": "solo",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 2,
    "start": 0,
    "docs": [
      {
          <大型嵌套的JSON元素>
      },
      {
          <大型嵌套的JSON元素>
      }
    ]
  }
}

现在,在我的Golang应用程序中,我想快速删除"responseHeader",以便只返回"response"。我该如何做到这一点而不创建大型结构?


编辑 1

evanmcdonnal的答案是解决这个问题的方法,但有一些小的拼写错误,这是我最终使用的代码:

var temp map[string]interface{}

if err := json.Unmarshal(body, &temp); err != nil {
    panic(err.Error())
}

result, err := json.Marshal(temp["response"])
英文:

I have a solr response in JSON format which looks like this:

 {
  &quot;responseHeader&quot;: {
    &quot;status&quot;: 0,
    &quot;QTime&quot;: 0,
    &quot;params&quot;: {
      &quot;q&quot;: &quot;solo&quot;,
      &quot;wt&quot;: &quot;json&quot;
    }
  },
  &quot;response&quot;: {
    &quot;numFound&quot;: 2,
    &quot;start&quot;: 0,
    &quot;docs&quot;: [
      {
          &lt;Large nested JSON element&gt;
      },
      {
          &lt;Large nested JSON element&gt;
      }
    ]
  }
}

Now, in my Golang app, I would like to quickly remove the "responseHeader" so that I can return the "response" alone. How can I do this without creating large structures?


Edit 1

The answer by evanmcdonnal was the solution to this problem, but it had some minor typos, this is what I ended up using:

var temp map[string]interface{}

if err := json.Unmarshal(body, &amp;temp); err != nil {
    panic(err.Error())
}

result, err := json.Marshal(temp[&quot;response&quot;])

答案1

得分: 5

以下是如何快速简单地完成这个任务的一个非常简短的示例。步骤如下:将数据解析为通用的map[string]interface{},然后假设没有错误,只对你想要的内部对象进行编组。

var temp := &map[string]interface{}

if err := json.Unmarshal(input, temp); err != nil {
     return err;
}

return json.Marshal(temp["response"])
英文:

Here's a really brief example of how to do this quickly and easily. The steps are; unmarshal into the universal map[string]interface{} then, assuming no errors, marshal only the inner object which you want.

var temp := &amp;map[string]interface{}

if err := json.Unmarshal(input, temp); err != nil {
     return err;
}

return json.Marshal(temp[&quot;response&quot;])

答案2

得分: 0

我写了一个名为ujson的包,可以在不解组JSON文档的情况下执行通用转换。

在Go Playground上运行:https://play.golang.org/p/RHlqJPeUEkz

input := []byte(`
{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "q": "solo",
      "wt": "json"
    }
  },
  "response": {
    "numFound": 2,
    "start": 0,
    "docs": [
      { "name": "foo" },
      { "name": "bar" }
    ]
  }
}`)

blacklistFields := [][]byte{
	[]byte("\"responseHeader\""), // 注意引号
}
b := make([]byte, 0, 1024)
err := ujson.Walk(input, func(_ int, key, value []byte) bool {
	for _, blacklist := range blacklistFields {
		if bytes.Equal(key, blacklist) {
			// 从输出中删除键和值
			return false
		}
	}

	// 写入输出
	if len(b) != 0 && ujson.ShouldAddComma(value, b[len(b)-1]) {
		b = append(b, ',')
	}
	if len(key) > 0 {
		b = append(b, key...)
		b = append(b, ':')
	}
	b = append(b, value...)
	return true
})
if err != nil {
	panic(err)
}
fmt.Printf("%s", b)
// 输出:{"response":{"numFound":2,"start":0,"docs":[{"name":"foo"},{"name":"bar"}]}}

你可以在博客文章中阅读更多相关信息。我将答案放在这里,以防其他人需要。

英文:

I wrote a package µjson to do exactly that: performing generic transformations on JSON documents without unmarshalling them.

Run on Go Playground

input := []byte(`
{
  &quot;responseHeader&quot;: {
    &quot;status&quot;: 0,
    &quot;QTime&quot;: 0,
    &quot;params&quot;: {
      &quot;q&quot;: &quot;solo&quot;,
      &quot;wt&quot;: &quot;json&quot;
    }
  },
  &quot;response&quot;: {
    &quot;numFound&quot;: 2,
    &quot;start&quot;: 0,
    &quot;docs&quot;: [
      { &quot;name&quot;: &quot;foo&quot; },
      { &quot;name&quot;: &quot;bar&quot; }
    ]
  }
}`)

blacklistFields := [][]byte{
	[]byte(`&quot;responseHeader&quot;`), // note the quotes
}
b := make([]byte, 0, 1024)
err := ujson.Walk(input, func(_ int, key, value []byte) bool {
	for _, blacklist := range blacklistFields {
		if bytes.Equal(key, blacklist) {
			// remove the key and value from the output
			return false
		}
	}

	// write to output
	if len(b) != 0 &amp;&amp; ujson.ShouldAddComma(value, b[len(b)-1]) {
		b = append(b, &#39;,&#39;)
	}
	if len(key) &gt; 0 {
		b = append(b, key...)
		b = append(b, &#39;:&#39;)
	}
	b = append(b, value...)
	return true
})
if err != nil {
	panic(err)
}
fmt.Printf(&quot;%s&quot;, b)
// Output: {&quot;response&quot;:{&quot;numFound&quot;:2,&quot;start&quot;:0,&quot;docs&quot;:[{&quot;name&quot;:&quot;foo&quot;},{&quot;name&quot;:&quot;bar&quot;}]}}

You can read more about it on the blog post. I put the answer here just in case someone else might need it.

huangapple
  • 本文由 发表于 2016年2月17日 03:20:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/35441254.html
匿名

发表评论

匿名网友

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

确定