我看过几篇有类似错误的文章,但似乎没有一篇适合我。我看过弹珠和其他许多样品,但仍然无法确定错误所在。
我在面料2.x。下面的chaincode在保存数据时工作得很好,但在读取时失败,并显示以下消息:
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 chaincode的事务序列化器出于某种原因不喜欢它。如果您确实需要omitempty
用于这些字段,您可以添加任何其他哑字段。
你可以添加一个布尔值…
type Asset struct {
Dumb bool `json:"dumb"`
Field1 string `json:"field1,omitempty" metadata:",optional"`
Field2 string `json:"field2,omitempty" metadata:",optional"`
}
…或者将key/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
检查并以我自己的格式返回序列化错误;也许对你的案子有用。
或者您可以从ReadAsset
返回string
而不是*Asset
作为解决方法,以避免导致错误的检查,以便仅在客户端中对其进行反序列化。事实上,我发现在CreateAsset
中接收string
并不太连贯,但在ReadAsset
中返回*Asset
。我会对两者使用相同的格式(*Asset
,最好,除非你被你的问题所困扰)。
我发现了这个问题,这里提到了这个bug:
在struct属性的JSON标签中提供额外的有效数据会导致模式失败。
这个bug已经关闭大约一年了,然而,我仍然会遇到这种行为。使用medatada
重写JSON属性也不起作用。
像这样使用结构体效果很好:
type Asset struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
}