0

I am trying to deserialize a local file in my project which is a json file. However I am getting this error with the current code:

"Unexpected character encountered while parsing value: G. Path '', line 0, position 0"

C# code

string filepath = Application.StartupPath + @"\city.list.json";
for(int i = 0; i< 40; i++)
{
    foreach (string x in File.ReadLines(filepath))
    {
        if(x.Contains("id") || x.Contains("name"))
        {
            var data = JsonConvert.DeserializeObject<City.values>(filepath);
            //City city = JsonConvert.DeserializeObject<City>(File.ReadAllText(filepath));
            //cityList.Add(data.name, data.id);
        }
        else
        {

        }
    }
}

class City
{
    [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
    public class values
    {
        [JsonProperty(PropertyName = "id")]
        public string id { get; set; }

        [JsonProperty(PropertyName = "name")]
        public string name { get; set; }
    }
}

Json file I am trying to deserialize from. This is just a quick sample taken out from the file. It is quite large ^^

[
   {
      "id":707860,
      "name":"Hurzuf",
      "country":"UA",
      "coord":{
         "lon":34.283333,
         "lat":44.549999
      }
   },
   {
      "id":519188,
      "name":"Novinki",
      "country":"RU",
      "coord":{
         "lon":37.666668,
         "lat":55.683334
      }
   },
9
  • You need a class that has an array of City, you currently do not have that Commented Mar 27, 2018 at 19:46
  • 1
    Something is wrong here, why do you read the file line-by-line but deserialize the filePath? You should read all the text into a single string and deserialize that, no loop required. Commented Mar 27, 2018 at 19:47
  • Thanks for the optimization suggestion Ron :D , ehm the file is 1.8milion lines long so i am just trying to get the 40 first lines in the file, thats why i am doing the for loop. Can i still do it your way just getting the first 40 lines without loop? Commented Mar 27, 2018 at 19:49
  • 1
    No, because taking a random "chunk" out of a JSON file isn't valid JSON, there are closing brackets that will be missing. Commented Mar 27, 2018 at 19:49
  • 2
    Do you understand, that you read file in loop 40 times, then for each string you want to deserialize that string (part of json) but instead you deserialize the path to file....? Commented Mar 27, 2018 at 19:50

1 Answer 1

3

You seem to have some huge misconceptions of how JSON deserializing works. First thing to address is you shouldn't be iterating through the lines of the json file. As pointed out in the comments, your JSON file is very large (~1.8 million lines) so your best bet is to use the JsonReader overload of DeserializeObject(), see Json.NET performance tips:

List<City.values> cities = new List<City.values>();
string filepath = Application.StartupPath + @"\city.list.json";
using (StreamReader sr = new StreamReader(filepath))
using (JsonReader reader = new JsonTextReader(sr))
{
    JsonSerializer serializer = new JsonSerializer();
    // read the json from a stream
    // json size doesn't matter because only a small piece is read at a time from the HTTP request
    cities = JsonConvert.DeserializeObject<List<City.values>>(reader);
}

Draw your attention to this line:

cities = JsonConvert.DeserializeObject<List<City.values>>(reader);

Here we leverage JSON.NET to deserialize. The difference between your code and the code I included here is that your JSON is a collection of objects, what this means is you need to deserialize into a collection of your City.values objects, in this case I used a List<T>.

Now we have a variable cities that is a collection of City.values objects that are included in your JSON.

Sign up to request clarification or add additional context in comments.

6 Comments

If the file is long (which it is, at 1.8milion lines), I would not do this. I would instead stream directly. See newtonsoft.com/json/help/html/Performance.htm#MemoryUsage as well as Can Json.NET serialize / deserialize to / from a stream?.
@dbc good call, I thought OP was using RealAllLines() at first (which is effectively the same as ReadAllText). I added a note on performance in the question
Thank you, really appriciate the answer. However. I am only intrested in deserializing the "id" and "name" row in the file. I had this solution earlier but i found no way to deserialize the specific rows i wanted.
@HelpIsNeeded - Simply omit the properties you don't want from your c# data model and the serializer will skip them as it deserializes from the file stream.
@HelpIsNeeded your class can just be those properties. You dont have to have a POCO that matches the entire object
|