每天进步一点点:custom_json操作中,分隔符引发的惨案
hive-105017·@oflyhigh·
0.000 HBD每天进步一点点:custom_json操作中,分隔符引发的惨案
在之前的[领空投的帖子](https://hive.blog/hive-105017/@oflyhigh/58uqtp)中,我曾说到,领空投以及交易空投币***本质都是使用HIVE链上的Custom operation(custom_json_operation)***。  (图源 :[pixabay](https://pixabay.com/photos/lightbulb-idea-creativity-base-3104355/)) 我们可以使用HiveSigner或者Keychain来生成并广播相应的`custom_json`来完成相关操作。不过作为一个爱折腾的半吊子程序员,我还是喜欢自己写代码去完成。 # 简单介绍custom_json 说到`custom_json`,我当初还真特意研究过一番,并且还专门写了一篇文章:[每天进步一点点:custom_json & follow\unfollow\mute\unmute](https://hive.blog/hive-105017/@oflyhigh/customjson-and-follow-unfollow-mute-unmute),在里边介绍了`custom_json`结构、大致实现以及示范了follow\unfollow\mute\unmute几项功能。 所以,这次我们可以拿来直接使用,就以claim_duat为例: > 首先我们要填充的结构大致是这样的: ``` op_custom_json = ['custom_json', { 'required_auths': [], 'required_posting_auths': [], 'id': '', 'json': '' }] ``` `id`是这个字符串,从上述截图中,不难看出id就是`duat_drop_claim`。 因为领取空投,使用POSTING授权,所以`required_auths`保留为空,`required_posting_auths`添加上对应账户的id,比如说`["oflyhigh.test"]`。 而`json`信息,在Pthon中则是这样的内容`json_data ={"claim":True}`,要把它添加到上述结构中,需要将其转换成字符串,我使用的是`json.dumps(json_data)`。 完成结构填充后,对其进行签名,并广播即可。 # 广播成功后的显示差异 然而当我广播成功后,我发现,在链上我广播的内容看起来是这个样子: > 而查看别人广播的内容,看起来都是这个样子的(重新模拟生成了一下): > 你注意到两者的差异了没有?虽然我确定,我前边广播的内容`"{"claim": true}"`并不影响我领取空投,但是明显这样的`{"claim":true}`看起来更舒服! # 显示差异的原因(表象——空格) 是什么导致这些差异呢(多了一圈双引号)?我百思不得其解。在其它一些区块链浏览器上,我的操作看起来也都是正常的,并且它确实起作用了,说明我的JSON没错,所以我只能将其归结为hiveblocks.com上解析&显示的问题。 但是新问题来了,为啥别人的显示和解析没问题呢?为此我进行了各种尝试: * 直接手工编码字符串 * 将True替换成true并直接编码到字符串 * 使用str()来将词典转换成字符串 当我即将被各种尝试折磨疯了以后,对比才发现,上述`"{"claim": true}"`与`{"claim":true}`的差异不单单在于""的问题,前者`:`与`true`之间其实还有一个` `空格,而这个不仔细观察是注意不到的。 当我试着用直接手工编码字符串的方式直接广播不带空格的字符串`"{\"claim\":true}"`,发现一切都变正常了。 # 根本原因——json库的参数 这或许可以算是一种解决方法,至少在领空投这个事情上,这样操作是完全没有问题的。但是这岂不是意味着以后再写其它`custom_json`时,我都要去手工生成字符串了?简单一点的还好,如果遇到复杂的,我岂不是要累死了? 所以,***找出为何`json.dumps()`会帮我添加上一个空格这样才能彻底解决问题***。 为此,我特意看了Python中json库的文档:[json — JSON encoder and decoder](https://docs.python.org/3/library/json.html),来看看用法和参数先: >`json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)` 最先怀疑的是`indent`参数,但是看到文档中说使用默认值就是最紧凑的形式处理了: >If indent is a non-negative integer or string, then JSON array elements and object members will be pretty-printed with that indent level. An indent level of 0, negative, or "" will only insert newlines. ***`None (the default) selects the most compact representation.`***Using a positive integer indent indents that many spaces per level. If indent is a string (such as "\t"), that string is used to indent each level. 都已经最紧凑了,我还能有啥办法?愁死我了!不过接着往下看,又发现`separators`参数: >If specified, separators should be an (item_separator, key_separator) tuple.***` The default is (', ', ': ') if indent is None and (',', ': ') otherwise`***. To get the most compact JSON representation, you should specify (',', ':') to eliminate whitespace. >Changed in version 3.4: Use (',', ': ') as default if indent is not None. 注意我划重点加粗加斜体的那句,就是说当我们选择最紧凑的模式时(***indent is None***),分隔符上还是给加了一个空格(***`(', ', ': ')`***),这就是我们`"{"claim": true}"`中`:`后边空格之所以冒出来的来缘故了! 我有些搞不懂写这个库的程序员的思路了,***明明设置了一个参数`indent`,并说这个参数默认时,是最紧凑的方式。然后又在分隔符后边加了个空格***,这是什么逻辑? 仔细看文档,发现`separators`参数的说明中,还有一句: >***`To get the most compact JSON representation, you should specify (',', ':') to eliminate whitespace.`*** 请问,之前明明说了最紧凑`most compact representation`,又让我指定`separators`参数来获取最紧凑的表示形式,恕我英语学得不好,形容词最高级之上还有最高级吗? # 问题的解决 好吧,尽管这这奇怪的逻辑相当不爽,但是总算找到问题的原因了,所以我只需做如下修改,就可以愉快地使用`json.dumps`了: >`json.dumps(json_data, separators=(',',':'))` 所以,就这样,为了一个其实并没有什么影响的问题,耗费了三两天的时间,这大概可以算作惨案了吧!  (图源 :[pixabay](https://pixabay.com/photos/upset-sad-confused-figurine-534103/)) /(ㄒoㄒ)/~~ 不对,应该是最惨的惨案!!还不对,应该是最最最惨的惨案了!!! # 相关链接 * [json — JSON encoder and decoder](https://docs.python.org/3/library/json.html) * [每天进步一点点:custom_json & follow\unfollow\mute\unmute](https://hive.blog/hive-105017/@oflyhigh/customjson-and-follow-unfollow-mute-unmute)
👍 joeyarnoldvn, ethanlee, bilpcoinbot, hungryharish, julesquirin, cnfund, gmlgang, icon123456, steemindian, btshuang, mygod, liangfengyouren, atma-yoga, hungryanu, therealyme, warmstill, drricksanchez, lnakuma, oldman28, joele, dine77, janaveda, curly-q, wolf-dawg, lestrange, soufianechakrouf, jamzmie, mermaidvampire, julian2013, nextgen622, catwomanteresa, archisteem, pishio, kimzwarch, travelgirl, quiltedduckfarm, kathyto, davidke20, japanguide, pet.society, cnstm, digital.mine, rj-photo, namchau, joeliew, vamos-amigo, iipoh06, voxmortis, bichen, steemegg, likuang007, lianjingmedia, mia-cc, fintian, vickyli, jywahaha, ioioioioi, newhope, bilpcoinrecords, steemaction, magicmonk, rasalom, roberto58, alpha-omega, htliao, minloulou, otom, nanosesame, minminlou, moleah, love5200, andyjim, hmayak, dailyke20, jimhawkins, fatman, investegg, bert0, memeteca, tresor, bnk, tomiscurious, polkallen, mangou007, zerofive, lordbutterfly, zwhammer, chenlocus, dses, hivefolks, gtpjfoodbank, dbfoodbank, weddinggift, hive.friends, hyborian-strain, yestermorrow, tvb, fusion.lover, omnivori, atyh, bboyady, starrouge, jongcl, aafeng, dapeng, mrspointm, mrpointp, suhunter, logic, hivewatchers, steemcleaners, votehero, msp-makeaminnow, eturnerx-honey, seikatsumkt, newsflash, teachblogger, lovelemon, tingjie, fredo77200, sasaadrian, ying82, my451r, zhangyan-123, ratnaayub, penguinpablo, funnyman, alphacore, hungrybear, cryptonized, jacuzzi, elgringoviejo, d-hive, bricksolution, chinchilla, lovequeen, ivet, yanhan, annepink, deanliu, maxwellmarcusart, gloriaolar, ottomu, uruiamme, joythewanderer, etherpunk, ace108, passion-fruit, fortune-master, floatinglin, blogstats, itchyfeetdonica, tina1219, steemgreen, idx, laoyao, midnightoil, xiaohui, helene, exec, abit, cowboyzlegend27, jychbetter, philipmak, yohjuan, bxt, nostalgic1212, nazomimatute1998, azazqwe, sunflor, susanli3769, weisheng167388, chenfuzi, rivalhw, marygong77777, sofs-su, mattsanthonyit, adm, kgsupport, ydolidia, abundancelife,