HyperLedger Fabric Java 合约参数传 JSON 字符串
合约中交易函数可以传多个参数,但是对于一些复杂参数这种方式就比较低效。对于复杂参数可以使用传 json 字符串的方式简化开发。
定义参数接收对象
@DataType
@Data
public class UserInfo {
@Property
String key;
@Property
String idCard;
@Property
String name;
@Property
String sex;
@Property
String birthday;
@Property
String phone;
}
编写合约交易函数
@Contract(
name = "UserContract",
info = @Info(
title = "User contract",
description = "user contract",
version = "0.0.1-SNAPSHOT",
license = @License(
name = "Apache 2.0 License",
url
contact = @Contact(
email = "f.carr@",
name = "User contract",
url
@Log
public class UserContract implements ContractInterface {
@Transaction
public UserInfo regUser(Context ctx , UserInfo userInfo) {
ChaincodeStub stub = ctx.getStub();
String user = stub.getStringState(userInfo.getKey());
if (StringUtils.isNotBlank(user)) {
String errorMessage = String.format("User %s already exists", userInfo.getKey());
log.log(Level.ALL , errorMessage);
throw new ChaincodeException(errorMessage);
}
stub.putStringState(userInfo.getKey() , JSON.toJSONString(userInfo));
return userInfo;
}
}
Fabric 实现方式
fabric-chaincode-shim
先将 json 字符串反序列化为 org.json.JSONObject
再通过反射的方式调用参数接收对象中字段的 set 函数将值绑定的目标参数接收对象中。
org.hyperledger.fabric.contract.execution.JSONTransactionSerializer#createComponentInstance
Object createComponentInstance(final String format, final String jsonString, final TypeSchema ts) {
final DataTypeDefinition dtd = this.typeRegistry.getDataType(format);
Object obj;
try {
obj = dtd.getTypeClass().getDeclaredConstructor().newInstance();
} catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e1) {
throw new ContractRuntimeException("Unable to to create new instance of type", e1);
}
final JSONObject json = new JSONObject(jsonString);
// request validation of the type may throw an exception if validation fails
ts.validate(json);
try {
final Map<String, PropertyDefinition> fields = dtd.getProperties();
for (final Iterator<PropertyDefinition> iterator = fields.values().iterator(); iterator.hasNext();) {
final PropertyDefinition prop = iterator.next();
final Field f = prop.getField();
f.setAccessible(true);
final Object newValue = convert(json.get(prop.getName()).toString(), prop.getSchema());
f.set(obj, newValue);
}
return obj;
} catch (SecurityException | IllegalArgumentException | IllegalAccessException | InstantiationException | JSONException e) {
throw new ContractRuntimeException("Unable to convert JSON to object", e);
}
}
CLI 客户端调用
peer chaincode invoke -o orderer0.:7050 --ordererTLSHostnameOverride orderer0. --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations//orderers/orderer0./msp/tlscacerts/tlsca.-cert.pem -C businesschannel -n hyperledger-fabric-contract-java-demo --peerAddresses 1.:7051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org1./peers/1./tls/ca.crt --peerAddresses 2.:7051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org2./peers/2./tls/ca.crt -c '{"function":"UserContract:regUser","Args":["{\"key\":\"user-0\",\"idCard\":\"610102198910210321\",\"name\":\"哈哈哈哈lx\",\"sex\":\"男\",\"birthday\":\"1980-01-27\"}"]}
响应结果如图: