首页 > 解决方案 > 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 转换为字节并保存吗?我知道这可行,是否“仅”用于数据验证目的?

无论如何,非常感谢。

标签: gohyperledger-fabrichyperledger-chaincodechaincode

解决方案


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而不是*AssetfromReadAsset作为解决方法,以避免导致错误的检查,以便仅在客户端中对其进行反序列化。事实上,我发现接收一个stringin并没有多大连贯性CreateAsset,而是返回一个*Assetin ReadAsset。我会为两者使用相同的格式(*Asset最好是,除非您遇到问题)。


推荐阅读