提问人:markhorrocks 提问时间:11/17/2023 最后编辑:markhorrocks 更新时间:11/18/2023 访问量:122
如何使用 Golang 解码这个嵌套的 json?
How to decode this nested json with Golang?
问:
我正在尝试将嵌套的 json 解码为包含文件和数据的请求的一部分。
数据如下所示
{data: {"date_required":null}}
我最初没有包含完整的错误,因为我忘记记录它。
2023/11/17 23:40:35 error in decoding request body data
2023/11/17 23:40:35 invalid character '.' looking for beginning of value
我相信这个错误可能是由于表单数据不是JSON造成的,但不知道如何解决它。我的 Flutter 代码在我看来就像它发送了有效的 JSON。Content-Type 是,这可能是导致错误的原因。我相信我的代码的文件上传部分需要这个 Content-Type。multipart/form-data
该请求来自我的 Flutter 客户端,代码如下:
final multipartFile =
http.MultipartFile.fromBytes('file', bytes, filename: file?.name);
final request = http.MultipartRequest('POST', Uri.parse(user.fileUrl));
request.files.add(multipartFile);
request.headers.addAll(headers);
String dateRequiredStr = dateRequired != null
? jsonEncode({'date_required': dateRequired})
: jsonEncode({'date_required': null});
request.fields['data'] = dateRequiredStr;
在我的go API中,我正在这样做。
模型(根据下面的答案编辑):
type FileRequiredDate struct {
DateRequired pgtype.Date `json:"date_required"`
}
type FileRequiredDateData struct {
Data FileRequiredDate `json:"data"`
}
法典:
func (rs *appResource) uploadTranscriptAudioFile(w http.ResponseWriter, r *http.Request) {
start := time.Now()
const maxUploadSize = 500 * 1024 * 1024 // 500 Mb
var requiredByDate FileRequiredDateData
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&requiredByDate)
if err != nil {
log.Println("error in decoding request body data")
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
file, handler, err := r.FormFile("file")
if err != nil {
log.Println(err)
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
defer file.Close()
fileSize := handler.Size
if fileSize > maxUploadSize {
http.Error(w, "FILE_TOO_BIG", http.StatusBadRequest)
return
}
fileName := handler.Filename
httputil.DumpRequest
-> 内容类型:multipart/form-data
编辑:在回答这个问题之后,我编辑了这样的代码:
mr, err := r.MultipartReader()
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for {
part, err := mr.NextPart()
// This is OK, no more parts
if err == io.EOF {
break
}
// Some error
if err != nil {
log.Println("multipart reader other error")
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
log.Println(part.FormName())
if part.FormName() == "data" {
log.Println("multipart reader found multipart form name data")
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&requiredByDate)
if err != nil {
log.Println("error in decoding request body data")
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}
}
if part.FormName() == "file" {
file, handler, err := r.FormFile("file") <-- error here
if err != nil {
log.Println("error getting form file")
log.Println(err.Error())
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusInternalServerError)
return
}
defer file.Close()
guid := xid.New()
userId := getUserFromJWT(r)
user, err := getUser(rs, int64(userId))
if err != nil {
log.Println("user not found")
log.Println(err.Error())
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}
err = uploadToMinio(rs, file, fileSize, fileName, guid.String(), userId)
----
这给了我这个输出:
2023/11/17 23:23:30 data
2023/11/17 23:23:30 file
编辑:
我通过使用代替decoder := json.NewDecoder(part)
decoder := json.NewDecoder(r.Body)
现在我得到了.似乎我应该以某种方式使用 part,但 part 没有文件属性。 r.Body 不再可用,因为我将表单数据添加到了 mulitpart 请求中。这似乎是一个不同的问题。error getting form file
答:
2赞
segFault
11/17/2023
#1
虽然这不会解决 404 问题(请使用请求处理程序代码更新您的问题),但您的结构似乎与您发送的内容不匹配。你可以做这样的事情来解决这个问题:
type FileRequiredDate struct {
DateRequired pgtype.Date `json:"date_required"`
}
type FileRequiredDateData struct {
Data FileRequiredDate `json:"data"`
}
这应该按预期解码请求正文。
至于 404,您应该仔细检查客户端代码发送的请求路径和方法是否与服务器请求处理程序路径和方法匹配。
评论
0赞
markhorrocks
11/17/2023
我使用了您的代码,但出现解析错误,如更新的问题中所述。原始 404 错误由我硬编码以指示解析错误。
0赞
mkopriva
11/17/2023
@markhorrocks 题中的代码是硬编码的,这是和不是。您的声明和代码不太一致,这使得提出准确的解决方案变得更加困难。此外,在您更新的问题中,您没有“描述”错误;我们不知道您是真的指的是“解析错误”(这表示传入的 JSON 无效),还是您的意思是“解码错误”,这可能表明 JSON 值仍然与目标类型不匹配。StatusBadRequest
400
404
0赞
mkopriva
11/17/2023
@markhorrocks鉴于您未能提供有关您遇到的问题的足够信息,我只能猜测问题可能是什么:一个原因可能是并且不能很好地配合在一起,有时指针(即)可以解决该问题。另一个原因可能只是不支持 JSON 中发送的 JSON 数据格式,在这种情况下,不应使用可以处理传入 JSON 值的类型。null
pgtype.Date
*pgtype.Date
pgtype.Date
pgtype.Date
0赞
markhorrocks
11/17/2023
我已经提供了相关代码的每一行。我的模型中有数百个模型,它们可以很好地处理 Flutter 帖子中的空数据。我不知道解码和 json 解析错误之间甚至存在差异。这就是这个网站存在的原因。pgtype.Date
0赞
mkopriva
11/17/2023
@markhorrocks代码在这一点上是无关紧要的;显示确切的错误消息是什么,输出是什么?log.Println(err.Error())
评论
FileRequiredDateData
的结构与 JSON 的结构不匹配。该类型有两个单独的“同级”字段;而不是像 JSON 那样嵌套在另一个中。