go - golang结构链码行为中的json编码
问题描述
我看过几篇有类似错误的文章,但似乎没有一个对我有用。我已经看过弹珠样品以及许多其他样品,但仍然无法查明错误。
我在织物 2.x 中。下面的链码在保存数据时工作得很好,但在读取以下消息时失败:
ERROR] Error submitting transaction: No valid responses from any peers. Errors:
peer=org1peer-api.127-0-0-1.nip.io:8080, status=500, message=Error handling success response. Value did not match schema:
1. return: Additional property field1 is not allowed
2. return: Additional property field2 is not allowed
3. return: field1,omitempty is required
4. return: field2,omitempty is required
type Asset struct {
Field1 string `json:"field1,omitempty"`
Field2 string `json:"field2,omitempty"`
}
func (c *AssetContract) CreateAsset(ctx contractapi.TransactionContextInterface, assetID string, values string) (bool, error) {
// convert json input to byte array
txData := []byte(values)
// convert byte array to HlpAsset struct
asset := new(asset)
err = json.Unmarshal(txData, &asset)
// convert struct back to bytes
txBytes, err := json.Marshal(asset)
return true, ctx.GetStub().PutState(assetID, txBytes)
}
func (c *AssetContract) ReadAsset(ctx contractapi.TransactionContextInterface, assetID string) (*Asset, error) {
txBytes, _ := ctx.GetStub().GetState(assetID)
// convert byte array to HlpAsset struct
asset := new(Asset)
err = json.Unmarshal(txBytes, &asset)
return asset, nil
}
使用以下输入数据进行测试:
assetID: "3",
values: "{\"field1\":\"123\",\"field2\":\"a05\"}"
此外,我不确定为什么需要 Unmarshal/Marshal。我不能将字符串化的 JSON 转换为字节并保存吗?我知道这可行,是否“仅”用于数据验证目的?
无论如何,非常感谢。
解决方案
在omitempty
字段中,也设置metadata:",optional"
为通过验证。而且您不能json:"omitempty" metadata:",optional"
在模型的所有字段上进行设置。默认的 Fabric 2.X Go 链码的事务序列化器出于任何原因都不喜欢它。如果您真的需要omitempty
这些字段,您可以添加任何其他哑字段。
您可以添加一个愚蠢的布尔值...
type Asset struct {
Dumb bool `json:"dumb"`
Field1 string `json:"field1,omitempty" metadata:",optional"`
Field2 string `json:"field2,omitempty" metadata:",optional"`
}
...或将密钥/ID 本身添加到模型中...
type Asset struct {
ID string `json:"id"`
Field1 string `json:"field1,omitempty" metadata:",optional"`
Field2 string `json:"field2,omitempty" metadata:",optional"`
}
...或文档类型...
type Asset struct {
DocType string `json:"docType"`
Field1 string `json:"field1,omitempty" metadata:",optional"`
Field2 string `json:"field2,omitempty" metadata:",optional"`
}
作为替代方案,您可以尝试覆盖默认 ContractChaincode 的 TransactionSerializer ( https://pkg.go.dev/github.com/hyperledger/fabric-contract-api-go/contractapi#ContractChaincode )。我在将已经有自己的输入验证的链码从 1.X 迁移到 2.X 时已经这样做了,以避免metadata
检查并以我自己的格式返回序列化错误;并且可能适用于您的情况。
或者,您可以返回 astring
而不是*Asset
fromReadAsset
作为解决方法,以避免导致错误的检查,以便仅在客户端中对其进行反序列化。事实上,我发现接收一个string
in并没有多大连贯性CreateAsset
,而是返回一个*Asset
in ReadAsset
。我会为两者使用相同的格式(*Asset
最好是,除非您遇到问题)。
推荐阅读
- python - Unclear behavior with exception during asyncio task clean-up
- reactjs - How to get the previous state in React functional component?
- node.js - No coverage information is generated for vscode extension using nyc
- javascript - Passing an object prop to a React component in a mapping
- spring-statemachine - Configuring spring (uml) state machine (timers) for unit tests
- excel - Loop through multiple files in folder and copy/paste to master file
- javascript - 使用 tsyringe 使用构造函数参数注册服务
- c# - 在石英 .net 5 中添加自定义作业工厂
- xamarin.forms - 使用objective-c指针绑定iOS库错误?
- c++ - 为什么`std::set::extract`不支持异构查找作为`std::set::find`?