Go区块链API GET请求报错:invalid character 'þ'寻找值起始位置
问题根源与解决方案
核心问题定位
你遇到的invalid character 'þ' looking for beginning of value错误,本质是响应内容包含无效UTF-8字符或非JSON格式数据,由以下代码问题导致:
- 格式化符误用:
CalculateHash函数中对字符串类型的PropertyAddress使用了浮点数格式符%f,导致生成的字符串包含无效字节; - 编码方式混用:
Contract.ToBytes()用Gob编码存储数据,但后续代码尝试用JSON解析这些二进制字节,解析失败后产生错误响应; - 区块链逻辑错误:
AddBlock方法错误复用前一个区块的Contract数据创建新块,而非使用传入的合同数据,进一步导致数据混乱。
分步修复方案
1. 修复CalculateHash的格式化错误
修改blockchain/Blockchain.go中的CalculateHash函数,将PropertyAddress的格式符从%f改为字符串格式符%s:
func CalculateHash(data Contract, prevHash string, timestamp time.Time) string { record := fmt.Sprintf("%s%d%d%s%s%s%s%s%f%f%f%t%s%s", data.ID, data.StartTime, data.ContractDuration, data.EndTime, data.CurrentStage, data.PropertyHash, data.PropertyID, data.PropertyAddress, // 此处将%f改为%s data.RentAmount, data.DepositAmount, data.DepositDeductions, data.ContractSigned, prevHash, timestamp.Format(time.RFC3339), ) h := sha256.New() h.Write([]byte(record)) hashed := h.Sum(nil) return hex.EncodeToString(hashed) }
2. 统一数据编码方式
将Contract.ToBytes()改为JSON编码,与后续解析逻辑统一:
func (c *Contract) ToBytes() []byte { data, err := json.Marshal(c) if err != nil { log.Fatalf("failed to encode contract: %v", err) } return data }
3. 修正AddBlock的逻辑错误
当前AddBlock错误复用前一个区块的数据,改为使用传入的合同数据创建新块:
func (bc *Blockchain) AddBlock(contract Contract, prevHash string) { newBlock := CreateBlock(len(bc.Blocks), contract, prevHash) bc.Blocks = append(bc.Blocks, newBlock) }
4. 确保响应数据可正确序列化
检查contracts.ListContracts()函数,确保它从区块链中正确解码Contract数据:
// contracts包示例实现 func ListContracts() ([]blockchain.Contract, error) { bc := blockchain.NewBlockchain() var contractList []blockchain.Contract for _, block := range bc.Blocks { var contract blockchain.Contract err := json.Unmarshal(block.Data, &contract) if err != nil { return nil, err } contractList = append(contractList, contract) } return contractList, nil }
5. 优化响应日志中间件
避免将二进制数据直接转为字符串,防止引入无效字符:
// 导入必要包:"encoding/base64"、"unicode/utf8" func (rl *responseLogger) Write(body []byte) (int, error) { if utf8.Valid(body) { rl.body = string(body) } else { rl.body = base64.StdEncoding.EncodeToString(body) } return rl.ResponseWriter.Write(body) }
验证修复
重启服务器后,再次发送GET localhost:8080/contracts请求,响应应返回标准JSON格式,错误消失。
内容的提问来源于stack exchange,提问作者Joe Izatt
相关产品推荐
相关产品推荐

