Encoding/Decoding multi-type fields in JSON?

xuanbao · · 831 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>Hi all, I&#39;d like to en/de/code JSON with Golang which may have multiple types in a given field, something like:</p> <pre><code>[{&#34;type&#34;: &#34;number&#34;, &#34;value&#34;: 15}, {&#34;type&#34;: &#34;string&#34;, &#34;value&#34;: &#34;Hello!&#34;}] </code></pre> <p>The &#34;value&#34; field can be string, number, boolean, etc: how to handle this?</p> <p><em>edit: I&#39;m grateful for suggestions to use <code>interface{}</code>, but that&#39;s a despicable antipattern I&#39;d really rather avoid. Is there any way to achieve this using multiple type-safe fields and JSON annotations to let more than one field map to the same field-name when encoding and decoding?</em></p> <p><em>edit 2: To be more specific, is there some way to do this (except that this doesn&#39;t work)?:</em></p> <pre><code>type FooStruct struct{ Type string StringValue `json:&#34;value&#34;` IntValue `json:&#34;value&#34;` FloatValue `json:&#34;value&#34;` BooleanValue `json:&#34;value&#34;` } </code></pre> <hr/>**评论:**<br/><br/>ilikeorangutans: <pre><p>Take a look at <a href="http://golang.org/pkg/encoding/json/#RawMessage" rel="nofollow">RawMessage</a> which lets you delay parsing of parts of the JSON. The example in the docs does pretty much what you are looking for. </p></pre>cathalgarvey: <pre><p>This might be my answer, thank you! Needs some experimentation to see how to implement the encoding end robustly but this is a clean-seeming way to handle decoding.</p></pre>djherbis: <pre><p>This is a little verbose, but it does what you want. <a href="https://play.golang.org/p/ZXudlXBdty" rel="nofollow">https://play.golang.org/p/ZXudlXBdty</a></p></pre>cathalgarvey: <pre><p>Thank you! This answers my question as to whether the JSON tagging system would suffice, and goes further to provide a working solution. Really cool, thanks.</p></pre>anhlh2: <pre><p>I have similar problem but the types and data of possible records are a bit more complex. I found <a href="https://github.com/mitchellh/mapstructure" rel="nofollow">mapstructure</a> and I like it, here is the solution to your question using mapstructure: <a href="http://pastebin.com/5Wbzk4ZB" rel="nofollow">http://pastebin.com/5Wbzk4ZB</a> </p></pre>IntellectualReserve: <pre><p>I haven&#39;t found a library I like for this yet. I&#39;m thinking about writing one. </p></pre>jerf: <pre><p>Responding to your subsequent edits, <code>interface{}</code> in this case isn&#39;t the despicable anti-pattern... it&#39;s just a request for <code>encoding/json</code> to use what it uses for interface{}. It isn&#39;t truly &#34;unrestricted&#34;.</p> <p>And for edit 2: No. <code>encoding/json</code> is a simple library. It has many weaknesses if you stress it, and you&#39;ll have to go find a more complicated library. Among its weaknesses is that it shares something that is true of a lot of static languages with simple JSON libraries, which is that if your JSON is <em>not</em> implicitly a statically-typed document, it has a hard time dealing with that. You&#39;ll end up having to do some manual work.</p></pre>drwiggly: <pre><p>Made a small wrapper that decodes with raw message and allows path access to the structure of the doc.</p> <p><a href="https://github.com/chrhlnd/dynjson" rel="nofollow">https://github.com/chrhlnd/dynjson</a></p> <p>That being said depending on what you&#39;re doing just decoding with 2 struct types may just be easier.</p> <p><a href="http://play.golang.org/p/9bPhTY66Gr" rel="nofollow">http://play.golang.org/p/9bPhTY66Gr</a></p></pre>cathalgarvey: <pre><p>Using different types for each value and partially decoding the type hint is actually the cleanest way I&#39;ve yet seen, thanks. It&#39;s a pity things like this either impose convoluted method like this and a runtime cost, or simple, dangerous and <em>still</em> runtime costly methods like <code>interface{}</code>…</p></pre>JHunz: <pre><p>The struct you decode into should define the value field as an interface{}. Then once you determine the type via the other field, do a runtime cast into a new variable of the appropriate type. </p> <p>switch decoded.Type {<br/> case &#34;number&#34;:<br/> intValue, ok := decoded.Value.(int)<br/> if !ok {<br/> // Error handling...<br/> }<br/> ...</p></pre>

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

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