I've tried to be as descriptive as I can be. If I wasn't specific enough about something, please let me know and I will further explain.
Thanks in advance!
I am trying to parse JSON data passed in the body of a POST request to my server. The client side request is being made from a web app written using React, the endpoint is on a server written in Go (code below). The server is correctly parsing the JSON data using a struct as a model, but only after it prints an error "unexpected end of JSON input" as well as an empty array (output below). I only print the parsed JSON once though, so I have no clue why this is happening. Also, if I follow up the POST with the same call multiple times, the behavior is correct sometimes.
The output of the log in the save function is:
[{user: "username", attribute: "playlist", match: true, value: "playlistID"}]
The output below was created when pressing the save button rapidly, therefore making the POST request many times. If I were to just press the save button once the output would be:
unexpected end of JSON input
[]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
unexpected end of JSON input
[]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
unexpected end of JSON input
[]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
[{username playlist true playlistID}]
save = () => {
var rules = [];
this.state.rules.map((rule, index) => {
var match = rule.matches[rule.state.match];
var value = rule.values[rule.state.value];
var newRule = {
user: this.props.user,
attribute: rule.attribute,
match: match,
value: value.UUID
};
rules.push(newRule);
return newRule;
});
console.log(rules);
Server.saveSmartPlaylist(rules);
};
export function saveSmartPlaylist(data) {
return axios({
method: "POST",
baseURL: "http://localhost:8080",
url: "/smartplaylist",
data: data
}).catch(err => {
console.log(err);
});
}
func Playlists(response http.ResponseWriter, request *http.Request) {
body, err := ioutil.ReadAll(request.Body)
if err != nil {
fmt.Println(err)
}
var rules []rule
err = json.Unmarshal(body, &rules)
if err != nil {
fmt.Println(err)
}
fmt.Println(rules)
rest.PostRequest(response, request, rules)
}
func PostRequest(response http.ResponseWriter, request *http.Request, v interface{}) {
response.Header().Set("Access-Control-Allow-Headers", "Content-Type")
response.Header().Set("Access-Control-Allow-Origin", "*")
response.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
response.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(response)
enc.SetEscapeHTML(false)
enc.Encode(v)
}
Guarding the actual usage of the parsed JSON inside an if that checks the request method solved my problem.
func Playlists(response http.ResponseWriter, request *http.Request) {
var rules []rule
if request.Method == http.MethodPost {
body, err := ioutil.ReadAll(request.Body)
if err != nil {
fmt.Println(err)
}
err = json.Unmarshal(body, &rules)
if err != nil {
fmt.Println(err)
}
var tracks []string
var userID string
for i := 0; i < len(rules); i++ {
rule := rules[i]
ruleTracks := PlaylistMatchValue(rule.User, rule.Match, rule.Value)
tracks = ruleTracks
userID = rule.User
}
updatePlaylist(userID, tracks)
}
rest.PostRequest(response, request, rules)
}
There is no need to ioutil.ReadAll(request.Body)
Better to
dec := json.NewDecoder(request.Body) err = dec.Decode(&rules)