Search code examples
c#listdictionaryxamarinjson.net

Newtonsoft JSON JsonReaderException when trying to deserialize multidimensional array


I have a script in my application that gathers some JSON data from my PHP REST API. The API uses json_encode() to serialize a multidimensional array that it has generated. The script within my app should deserialize this into the equivalent in C# so that I can loop through it as each sub-array represents a "row" of information from the database. However, I am presented with this error:

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: A. Path '', line 0, position 0.
  at Newtonsoft.Json.JsonTextReader.ParseValue () [0x002b3] in <2073514815234917a5e8f91b0b239405>:0 
  at Newtonsoft.Json.JsonTextReader.Read () [0x0004c] in <2073514815234917a5e8f91b0b239405>:0 
  at Newtonsoft.Json.JsonReader.ReadAndMoveToContent () [0x00000] in <2073514815234917a5e8f91b0b239405>:0 
  at Newtonsoft.Json.JsonReader.ReadForType (Newtonsoft.Json.Serialization.JsonContract contract, System.Boolean hasConverter) [0x0004a] in <2073514815234917a5e8f91b0b239405>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x000db] in <2073514815234917a5e8f91b0b239405>:0 
  at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x

The JSON (exactly as my app receives it from the server)

[{"type":"0","ID":"1","groupID":"0","authorID":"14","contents":"rfgwgfgdfssd","time_stamp":"0-0-0"}, {"type":"0","ID":"2","groupID":"0","authorID":"14","contents":"whwrgthwr","time_stamp":"0-0-0"}]

The Script

async void getUpdatesAsync()
        {
            Console.WriteLine("starting...");

            BackendConnect connectionHandler = new BackendConnect("vocal/posts/index.php");

            var updatesRequestInfo = new Dictionary<string, string>
            {

                {"sessionID", "c1f7a973c04e18a05342ecc2d16f7339"},
                {"type", "updateFeed"},
                {"userID", "14"}

            };

            connectionHandler.addData(updatesRequestInfo);

            string updatesReturn = await connectionHandler.sendForm(); // returns the json

            Console.WriteLine(updatesReturn); // the above json was copied and pasted from this output

            List<Dictionary<string, string>> updatesArray = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(updatesReturn); // this line causes error

            Console.WriteLine(updatesArray);

            //updatesArray.ForEach(Console.WriteLine);

        }

Another script in my app that also uses JsonConvert.DeserializeObject<DataType>(stringToDeserialize) works when a single dimensional array (["SUCCESS", "adlhfbaf"]) is given to the deserialize function and is able to parse this into a simple list, but fails when trying with the multidimensional array JSON above.

So far I have tried setting the updatesArray variable to an endless amount of different data types to see if that was the problem which I suspect it is, but as a newbie to languages like C# where you have to pre-define datatypes, I'm having a very hard time solving this one.

Essentially, I would like to import it as a list of dictionaries in C# so that I can use foreach() to loop through each index of the initial list and recover a dictionary where I can grab specific values (such as contents). Below is an example of what i'm looking for it to import (incorrect syntax I know but a rough idea at least)

var updatesArray = new List<Dictionary<string, string>>
                {
                    {
                        {"type", "0"},
                        {"ID", "1"},
                        {"groupID", "0"},
                        {"authorID", "14"},
                        {"contents", "rfgwgfgdfssd"},
                        {"time_stamp", "0-0-0"}
                    },
                    {
                        {"type", "0"},
                        {"ID", "2"},
                        {"groupID", "0"},
                        {"authorID", "14"},
                        {"contents", "whwrgthwr"},
                        {"time_stamp", "0-0-0"}
                    }

                };

Solution

  • My Issue

    Thank you so much to everyone who tried to solve my issue. Feeling pretty stupid with myself, I have now solved the issue xD. Big thanks to @Jason who mentioned viewing my variables contents in Hexadecimal. I wrote a few lines to convert the variable to Hex, copied this output and threw it into an online Hex to ASCII converter to find that I was misreading the output from my program and had ignored over double the amount of data was being returned by the PHP script due to a rogue print_r() command left within the PHP from testing which outputted the array before it was JSON encoded:

    Array
    (
        [0] => Array
            (
                [type] => 0
                [ID] => 1
                [groupID] => 0
                [authorID] => 14
                [contents] => rfgwgfgdfssd
                [time_stamp] => 0-0-0
            )
    
        [1] => Array
            (
                [type] => 0
                [ID] => 2
                [groupID] => 0
                [authorID] => 14
                [contents] => whwrgthwr
                [time_stamp] => 0-0-0
            )
    
    )
    [{"type":"0","ID":"1","groupID":"0","authorID":"14","contents":"rfgwgfgdfssd","time_stamp":"0-0-0"},{"type":"0","ID":"2","groupID":"0","authorID":"14","contents":"whwrgthwr","time_stamp":"0-0-0"}]
    

    Instead of just:

    [{"type":"0","ID":"1","groupID":"0","authorID":"14","contents":"rfgwgfgdfssd","time_stamp":"0-0-0"},{"type":"0","ID":"2","groupID":"0","authorID":"14","contents":"whwrgthwr","time_stamp":"0-0-0"}]
    

    Other Useful Possible Issues Summarised

    In order to assist others in the future, I see it being only fair for me to also mention some of the things I have learned from this thread COULD have been the problem with that error.

    Rogue Byte Order Marks / Zero Width Spaces

    • In C#, Unicode Characters like these can be removed with the String.Trim() function
    • Zero Width Space is always represented in unicode as U+200B
    • Byte Order Marks change based on what encoding has been used. For UTF-16, the BOM character is represented as U+FEFF
    • This means the fix for this problem is myString = myString.Trim(new char[]{'\uFEFF','\u200B'});

    Incorrect Datatype / Not Sure What Datatype To Use

    • Create your own object that fits the structure you require (as shown above in @ejwill's post)
    • Deserialize into this structure

    List / Dictionary Accidentally Imported From a Different Namespace

    • Make sure that none of the imported modules have a definition for List or Dictionary
    • If they do you can either:
    • Shorten your include so that only the object(s) you need from that module (IE: using System.Text; instead of using System;)
    • Or add the namespace to the front of your List / Dictionary declaration (IE: System.Collections.Generic.List<string> instead of just List<string>)