为什么要增加json库
我们在开发应用程序时,避免不了要和服务器进行通行,同理我们写EOSIO合约,也要进行数据的传递。EOSIO尽管给我提供了json_to_bin方法来对数据进行打包,使用起来过于麻烦,如果我们要使用别的语言(如python,json等)来开发sdk时,如果不了解EOSIO交易Action数据的打包格式,就会很麻烦。
但是如果我们使用json来作为交易Action的参数,那么所有的问题就会得到解决,客户端我们只要实现一个pack string的方法,就可以不依赖于json_to_bin API,同时交易传递大数据对象也能得到解决,所以抱着解决问题的目的,我们也应该为EOSIO合约开发库增加json解析库,降低合约开发的难度。
增加json解析库好处如下:
- json语法易于使用,兼容性广泛,是共享数据的最佳工具
- EOSIO交易数据打包过于复杂麻烦,开发效率不高
- EOSIO合约参数传递大数据时使用不方便
增加时应该注意什么
通过前面我们对EOSIO合约开发库的分析得知,要给合约开发库增加自己的开发库,需要注意以下几个方面
- 代码库尽量要写的精简,否则编译出来的合约体积会变大
- 代码中不能有系统操作,文件操作等,保持都是内存数据操作相关
- 代码中不能有按照平台定义宏,会导致有可能编译不过,还增加了代码体积
- 代码中不能有异常处理,若确实需要抛出逻辑异常,请使用开发库提供check函数来断言抛出
使用举例
能直接添加进入EOSIO合约开发库的json库不多,大多数都需要改动,这里以修改的picojson库来做简单实用说明
注意:picojson库只有一个头文件,使用直接拷贝进入就可以
原picojson地址:https://github.com/kazuho/picojson
EOSIO版picojson地址:https://download.youkuaiyun.com/download/whg1016/86506368
如下只讲解在合约中的使用情况
解析json字符串
std::string json_str = "{\"a\":1}";
picojson::value v;
std::string err;
err = picojson::parse(v, json_str);
结果对象存储于对象v中,接下来使用v可以获取对应的数据
判断某个字段存在
check( v.contains("account"), "invalid params(account)");
判断是否存在字段account,如果不存在使用check断言抛出异常
获取数值字段
// 获取字符串
auto account = v.get("account").get<std::string>();
// 获取数值
auto balance = v.get("balance").get<int64_t>();
详细可继续参考picojson的开发文档
字符串json序列化
picojson::value json;
json.set<picojson::object>(picojson::object());
json.get<picojson::object>()["from"] = picojson::value(from.to_string());
json.get<picojson::object>()["to"] = picojson::value(to.to_string());
json.get<picojson::object>()["quantity"] = picojson::value(quantity.to_string());
json.get<picojson::object>()["memo"] = picojson::value(std::string("transfer memo"));
action act( { {get_self(), name(active_permission)},{from, name(active_permission)}},
name("eosio.token"), name("transfer"), json.serialize());
act.send();
总结
- 给EOSIO增加开发库,相对来说简单,只要符合规则就是
- picojson库书写不够简洁,好处是相对其他的json库编译出来的体积小
后续计划
看过EOSIO源代码的朋友一定很欣赏EOSIO中fc库的使用,里面有一套自己实现的反射机制,后续计划尝试将fc库中反射相关的代码移植进来,这样可以大大增加合约的开发效率,不过带来的合约编译体积也会增大