Search code examples
javascriptjsonfetch-api

JSON deserialization results of object returns wrong values unless the property is accessed directly


This one is very odd and I struggled to even produce a title for the question that somewhat describes what happens. The problem occurs when calling an API (which I have also written) via the Javascript Fetch API, and then deserializing the results. The object that my API returns for this exact query (captured via ASP.NET's Swagger UI) is:

{
  "ppqDate": "2024-05-14T00:00:00",
  "anticipatedRetirementAge": 70,
  "createdOn": "2024-05-14T12:36:30.86"
}

I have redacted a lot of the data, the actual object is larger than this but these are relevant fields that will help me show you the problem. I retrieve this data using the following code:

    result = await fetch(url, {
        credentials: 'include'
    });
    var data = await result.json();
    console.log(data);
    console.log(data.ppqDate);
    return data;

The result of console.log(data) command is:

{
    "ppqDate": false,
    "anticipatedRetirementAge": false,
    "createdOn": "2024-05-14T12:36:30.86",
}

And the result of console.log(data.ppqDate) is:

2024-05-14T00:00:00

What I completely do not understand is why are the ppqDate and anticipatedRetirementAge fields showing up as false when printing the whole object but show up as actual, correct values when accessed directly? If instead of result.json() I first use result.text() it shows the correct values for all the fields but then when inevitably deserializing the object for some reason it converts some of the values to false.

As mentioned above accessing the values directly works throughout the app but when I try to serialize the object again to pass it to another API it serializes the values in question as false instead of their actual values, which causes me issues.

Does anyone know what could this possibly be? It seems to pick fields at random. It works for the createdOn field for example and a number of other numeric and string fields that I have redacted to keep this readable.


Solution

  • So I have managed to figure out what was causing a problem. I'll explain here and post a minimal reproducible example:

    The problem had nothing to do with the serialization/deserialization and the date formats in the end. It was actually very trivial, it turned out that I was accidentally assigning to the object's properties later on in the code, instead of evaluating them. The reason why it threw me in the loop and took me so long to figure this out can be summarised in this example (just javascript, no API calls needed):

    var object = {
        name: "nameBeforeChange"
    }
    
    console.log(object);
    console.log(object.name);
    
    object.name = "nameAfterChange";
    

    From above I would expect that the console would print the following:

    {
        "name": "nameBeforeChange"
    }
    
    nameBeforeChange
    

    What it actually returns is:

    {
        "name": "nameAfterChange"
    }
    
    nameBeforeChange
    

    This confused me for a while until @Pointy pointed out that console.log is asynchronous in Javascript. I was printing the object's contents directly after declaring it, so I assumed that the problem must have occurred before the print line, while actually it was happening much further in the code. This threw me in a loop and made me miss a very trivial mistake.

    Even knowing that console is asynchronous, it was still confusing to me as to why printing just one of the properties of the object was working instantly while printing the whole object seemed to wait until a pretty large portion of my code ran first. I have tried setting up a timeout and seeing how much I needed to delay the execution to get the print statement to catch up, as follows:

    var object = {
        name: "nameBeforeChange"
    }
    
    console.log(object);
    console.log(object.name);
    
    
    setTimeout(() => {
        object.name = "nameAfterChange";
        console.log(object);
    }, 2300)
    

    I had to slow it down by an entire 2.3 seconds just to print this object. I tested a range of values and anything below 2.3 seconds resulted in nameAfterChange being printed in the first print statement.

    I guess the main point is that I underestimated how slow printing objects is in the console.