问题描述
这只是我的 chaincod 包的摘录,但我使用函数 ListDoctorPermissions
在资产之后查询状态数据库,在我的情况下是具有以下结构的权限:
type Permission struct {
PermissionId string `json:"permissionId"`
DataCategory string `json:"dataCategory"`
PatientId string `json:"patientId"`
DoctorId string `json:"doctorId"`
Right string `json:"right"`
From string `json:"from"`
To string `json:"to"`
}
在部署链码的过程中,我在最后运行查询以测试链码,但出现错误:
Error: endorsement failure during query. response: status:500 message:"Error handling success response. Value did not match schema:\n1. return: Invalid type. Expected: array,given: string"
这是我调用链码的方式:
peer chaincode query -C mychannel -n permissions -c '{"Args":["ListDoctorPermissions","doctor1"]}'
在运行查询之前,我在状态数据库中创建了一个权限,其医生 ID 为“doctor1”,因此在数据库 (couchDB) 中查找复合键和条目应该没有问题。
// List all Permissions given to a doctor
func (s *SmartContract) ListDoctorPermissions(ctx contractapi.TransactionContextInterface,doctorId string) ([]byte,error) {
doctorIterator,err := ctx.GetStub().GetStateByPartialCompositeKey("permissionId",[]string{doctorId})
if err != nil {
return nil,err
}
fmt.Printf("the doctor Iterator is: %s",doctorIterator)
defer doctorIterator.Close()
var dataCategory string
var patientId string
var permissionId string
var permissions []byte
bArrayPermissionAlreadyWritten := false
for doctorIterator.HasNext() {
responseRange,err := doctorIterator.Next()
if err != nil {
return nil,err
}
objectType,compositeKeyParts,err := ctx.GetStub().SplitCompositeKey(responseRange.Key)
if err != nil {
return nil,err
}
fmt.Printf("the objectType is: %s",objectType)
dataCategory = compositeKeyParts[1]
patientId = compositeKeyParts[2]
permissionId = doctorId + dataCategory + patientId
fmt.Printf("the compositeKeyParts are: %s",compositeKeyParts[0],compositeKeyParts[1],compositeKeyParts[2])
permissionAsBytes,err := ctx.GetStub().GetState(permissionId)
if err != nil {
return nil,err
}
if bArrayPermissionAlreadyWritten == true {
newBytes := append([]byte(","),permissionAsBytes...)
permissions = append(permissions,newBytes...)
} else {
permissions = append(permissions,permissionAsBytes...)
fmt.Print(permissions)
}
fmt.Printf("Found a asset for index : %s asset id : ",objectType,compositeKeyParts[2])
bArrayPermissionAlreadyWritten = true
}
permissions = append(permissions,[]byte("]")...)
fmt.Print(permissions)
return permissions,nil
}
解决方法
我已经运行了上面提供的代码,您的评论是正确的,问题似乎源于使用 []byte
作为您的返回类型。我不完全确定为什么会发生这种情况,因为这应该是有效的返回类型。我会进一步研究这个,因为它可能是一个错误。
通过将返回类型转换为 string
并返回 string(permissions)
我在这样做时注意到,您的代码正在构建一个基于 getState 字节的字节数组。因此,另一种选择是将来自 get 状态调用的字节 json.Unmarshal
放入 Permission
结构并将其附加到数组中。然后,您可以将返回类型设为 []Permission
。
我现在建议您采用字符串或权限数组方法,因为我将不得不研究使用 []byte
作为返回类型会发生什么。
示例:
字符串:
// List all Permissions given to a doctor
func (s *SmartContract) ListDoctorPermissions(ctx contractapi.TransactionContextInterface,doctorId string) (string,error) {
doctorIterator,err := ctx.GetStub().GetStateByPartialCompositeKey("permissionId",[]string{doctorId})
if err != nil {
return "",err
}
fmt.Printf("the doctor Iterator is: %s",doctorIterator)
defer doctorIterator.Close()
var dataCategory string
var patientId string
var permissionId string
var permissions []byte
bArrayPermissionAlreadyWritten := false
for doctorIterator.HasNext() {
responseRange,err := doctorIterator.Next()
if err != nil {
return "",err
}
objectType,compositeKeyParts,err := ctx.GetStub().SplitCompositeKey(responseRange.Key)
if err != nil {
return "",err
}
fmt.Printf("the objectType is: %s",objectType)
dataCategory = compositeKeyParts[1]
patientId = compositeKeyParts[2]
permissionId = doctorId + dataCategory + patientId
fmt.Printf("the compositeKeyParts are: %s",compositeKeyParts[0],compositeKeyParts[1],compositeKeyParts[2])
permissionAsBytes,err := ctx.GetStub().GetState(permissionId)
if err != nil {
return "",err
}
if bArrayPermissionAlreadyWritten == true {
newBytes := append([]byte(","),permissionAsBytes...)
permissions = append(permissions,newBytes...)
} else {
permissions = append(permissions,permissionAsBytes...)
fmt.Print(permissions)
}
fmt.Printf("Found a asset for index : %s asset id : ",objectType,compositeKeyParts[2])
bArrayPermissionAlreadyWritten = true
}
permissions = append(permissions,[]byte("]")...)
fmt.Print(permissions)
return string(permissions),nil
}
[]权限:
// List all Permissions given to a doctor
func (s *SmartContract) ListDoctorPermissions(ctx contractapi.TransactionContextInterface,doctorId string) ([]Permission,[]string{doctorId})
if err != nil {
return nil,doctorIterator)
defer doctorIterator.Close()
var dataCategory string
var patientId string
var permissionId string
var permissions []Permission
for doctorIterator.HasNext() {
responseRange,err := doctorIterator.Next()
if err != nil {
return nil,err := ctx.GetStub().SplitCompositeKey(responseRange.Key)
if err != nil {
return nil,err := ctx.GetStub().GetState(permissionId)
if err != nil {
return nil,err
}
foundPermission := new(Permission)
err = json.Unmarshal(permissionAsBytes,foundPermission)
if err != nil {
return nil,err
}
permissions = append(permissions,*foundPermission)
}
fmt.Printf("Permissions %v",permissions)
return permissions,nil
}