每天进步一点点:custom_json操作中,分隔符引发的惨案

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@oflyhigh·
0.000 HBD
每天进步一点点:custom_json操作中,分隔符引发的惨案
在之前的[领空投的帖子](https://hive.blog/hive-105017/@oflyhigh/58uqtp)中,我曾说到,领空投以及交易空投币***本质都是使用HIVE链上的Custom operation(custom_json_operation)***。


![image.png](https://images.hive.blog/DQmZmFXZJXzczc2yUAHFSAcXJpnMsreEjDk4R4Q4f3CCP72/image.png)
(图源 :[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为例:
>![image.png](https://images.hive.blog/DQmdVnh74KpiGnCu2jZWX7ZqB41sRSEiL2nhqbf3MWbfK3C/image.png)

首先我们要填充的结构大致是这样的:
```
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)`。

完成结构填充后,对其进行签名,并广播即可。

# 广播成功后的显示差异

然而当我广播成功后,我发现,在链上我广播的内容看起来是这个样子:
>![image.png](https://images.hive.blog/DQmfPZCRZkiwXJcTDNkk9ZEfyyBFqsfcAXEBqeQatEHxGCb/image.png)

而查看别人广播的内容,看起来都是这个样子的(重新模拟生成了一下):
>![image.png](https://images.hive.blog/DQmVFZcA52xuwanfTSQU9fSugEdAbKXfXeZ6YK1yzp6hk6d/image.png)

你注意到两者的差异了没有?虽然我确定,我前边广播的内容`"{"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=(',',':'))`

所以,就这样,为了一个其实并没有什么影响的问题,耗费了三两天的时间,这大概可以算作惨案了吧!


![image.png](https://images.hive.blog/DQmcSFPLdXDVgSVSC5mTdMMZfYcyauPwpxbJzmE5EZUbus8/image.png)
(图源 :[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)
👍 , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,