Comment décoder le JSON imbriqué avec Golang est un défi auquel de nombreux développeurs sont confrontés lorsqu'ils traitent des structures de données complexes. Dans cet article, l'éditeur PHP Banana vous présentera en détail comment utiliser le package JSON dans Golang pour analyser et traiter les données JSON imbriquées. En étudiant le contenu de cet article, vous serez en mesure de gérer facilement diverses structures JSON complexes et d'obtenir une analyse et un traitement des données plus efficaces. Que vous soyez débutant ou développeur expérimenté, cet article vous fournira des conseils utiles et des exemples de code pour vous aider à résoudre le difficile problème du décodage JSON. Explorons la méthode de décodage du JSON imbriqué dans Golang !
J'essaie de décoder un json imbriqué dans le cadre d'une requête contenant un fichier et des données.
Les données ressemblent à ceci
{data: {"date_required":null}}
Je n'ai pas inclus l'erreur complète au départ parce que j'ai oublié de la documenter.
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
Je pense que cette erreur peut être causée par le fait que les données du formulaire ne sont pas JSON, mais je ne sais pas comment y remédier. Mon code Flutter semble envoyer du JSON valide. Le type de contenu est multipart/form-data
Cela peut être à l'origine de l'erreur. Je pense que ce type de contenu est requis pour la partie de téléchargement de fichiers de mon code.
La requête vient de mon client Flutter, le code est le suivant :
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;
Dans mon API go, je fais ça.
Modèle (édité en fonction des réponses ci-dessous) :
type FileRequiredDate struct { DateRequired pgtype.Date `json:"date_required"` } type FileRequiredDateData struct { Data FileRequiredDate `json:"data"` }
Code :
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
-> Type de contenu : multipart/form-data
Edit : Sur la base de la réponse à cette question, j'ai modifié le code comme suit :
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) ----
Cela me donne ce résultat :
2023/11/17 23:23:30 data 2023/11/17 23:23:30 file
Éditeur :
J'ai résolu le problème actuel en utilisant decoder := json.NewDecoder(part)
而不是 decoder := json.NewDecoder(r.Body)
Maintenant, je reçois une erreur lors de l'obtention du fichier de formulaire . Il semble que je devrais utiliser la pièce d'une manière ou d'une autre, mais la pièce n'a pas de propriétés de fichier. Depuis que j'ai ajouté les données du formulaire à la requête en plusieurs parties, r.Body n'est plus disponible. Cela ressemble à un problème différent.
Bien que cela ne résolve pas le problème 404 (veuillez mettre à jour votre question avec le code du gestionnaire de requêtes), votre structure ne semble pas correspondre à ce que vous envoyez. Vous pouvez procéder comme suit pour résoudre ce problème :
type FileRequiredDate struct { DateRequired pgtype.Date `json:"date_required"` } type FileRequiredDateData struct { Data FileRequiredDate `json:"data"` }
Cela devrait décoder le corps de la requête comme prévu.
Pour 404, vous devez vérifier que le chemin et la méthode de la requête envoyés par le code client correspondent au chemin et à la méthode du gestionnaire de requêtes du serveur.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!