API returns JSON surrounded by "[]". json.Unmarshal examples with text represented as a []byte are all in proper json format.

agolangf · · 460 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hello, Feeling a little dumb here. I have been trying to punMarshal an API response in json to a struct. All the examples I can find that show text examples are in the proper format for unmarshaling with []byte(&#39;{json}&#39;)<br/> Here is an example of one that works: <a href="https://play.golang.org/p/PjMR47dbzgu" rel="nofollow">https://play.golang.org/p/PjMR47dbzgu</a></p> <p>When I add the surrounding brackets to match my return, like in this example: <a href="https://play.golang.org/p/HE16jtwyKFE" rel="nofollow">https://play.golang.org/p/HE16jtwyKFE</a> , So the text example is surrounded like this: []byte(&#39;[{json}]&#39;</p> <p>I get the following error: &#34;json: cannot unmarshal array into Go value of type main.Example&#34;</p> <p>I keep getting stuck in a circle changing things around to match different examples I keep finding, but I can&#39;t find one that has the brackets around the outside and works.</p> <p>Any tips? Thanks</p> <hr/>**评论:**<br/><br/>shovelpost: <pre><p>Also when it doubt you can use a site like <a href="https://mholt.github.io/json-to-go/" rel="nofollow">https://mholt.github.io/json-to-go/</a> to generate a struct that is right for your JSON. </p> <p>For example</p> <pre><code>[ { &#34;type&#34;:&#34;example&#34;, &#34;data&#34;:{ &#34;name&#34;:&#34;abc&#34;, &#34;labels&#34;:{ &#34;key&#34;:&#34;value&#34; } }, &#34;subsets&#34;:[ { &#34;addresses&#34;:[ { &#34;ip&#34;:&#34;192.168.103.178&#34; } ], &#34;ports&#34;:[ { &#34;port&#34;:80 } ] } ] } ] </code></pre> <p>turns to</p> <pre><code>type AutoGenerated []struct { Type string `json:&#34;type&#34;` Data struct { Name string `json:&#34;name&#34;` Labels struct { Key string `json:&#34;key&#34;` } `json:&#34;labels&#34;` } `json:&#34;data&#34;` Subsets []struct { Addresses []struct { IP string `json:&#34;ip&#34;` } `json:&#34;addresses&#34;` Ports []struct { Port int `json:&#34;port&#34;` } `json:&#34;ports&#34;` } `json:&#34;subsets&#34;` } </code></pre> <p>You can then take that and split it so that it is clean in your code.</p></pre>anossov: <pre><p>That&#39;s a list of things, you have to unmarshal into a slice: <a href="https://play.golang.org/p/watM21z9eiZ" rel="nofollow">https://play.golang.org/p/watM21z9eiZ</a></p></pre>vapehound: <pre><p>Thanks!</p></pre>pharrisee: <pre><p>This can also be handy for building the boilerplate and then you simply customise (assuming you&#39;re using VSCode here of course):</p> <p><a href="https://marketplace.visualstudio.com/items?itemName=quicktype.quicktype" rel="nofollow">https://marketplace.visualstudio.com/items?itemName=quicktype.quicktype</a></p></pre>fourgbram: <pre><p>I had the same problem a couple of days ago and I think I solved it. Basically when you make a json.Decoder, you have to call <code>decoder.Token</code>before calling<code>decoder.Decode</code> Experience gophers please let me know if this is correct or not. </p></pre>vapehound: <pre><p>Thanks, <a href="/u/anssov" rel="nofollow">/u/anssov</a> ‘s solution worked for me. </p></pre>meowtasticly: <pre><p>I&#39;ve worked with a fair amount of JSON in Go and never knew decoder.Token existed... So no, I don&#39;t think that&#39;s correct for simple parsing like OP is working on.</p></pre>jerf: <pre><p>It isn&#39;t necessarily wrong or right, it depends on what you are trying to do. <code>decoder.Token</code> will yield the first token in the stream, which in this case is the opening of a list. Then anything else you try to consume will be as if that token wasn&#39;t there. If you have a list that you <em>know</em> has one element in it, which is what you really want to decode, then that is a fine solution in the real world of ugly JSON. However, bear in mind that with that approach you won&#39;t get any observable difference between <code>[{}]</code> (a list of one object) and <code>[{}, {}]</code> (a list of two objects); in both cases you&#39;ll skip the list open and decode the first object, and there will be no errors. In general after decoding the first object I&#39;d call .Token again and verify that it is a closed list as I expect, and at least log a warning if it isn&#39;t what I expected. I would also verify that the first token <em>is</em> the opening of a list before proceding and failing out if it is not.</p> <p>This technique has other uses as well. If you have a very long JSON document that is a list of smaller objects (just a lot of them), you can use this technique to pop off the list delimiter, then start iterating through the objects one at a time, instead of parsing the entire JSON file in one shot and marshaling all of the objects into RAM at once. Very useful stuff, in the right circumstances.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

460 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传