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
      }
   },
Aleks Andreev
  • 7,016
  • 8
  • 29
  • 37
  • You need a class that has an array of City, you currently do not have that – maccettura Mar 27 '18 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. – Ron Beyer Mar 27 '18 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? –  Mar 27 '18 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. – Ron Beyer Mar 27 '18 at 19:49
  • @maccettura hey, thanks. Could you please submit an example through answer? –  Mar 27 '18 at 19:50
  • 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....? – Markiian Benovskyi Mar 27 '18 at 19:50
  • @RonBeyer oh ye you are right, forgot about that. –  Mar 27 '18 at 19:51
  • I think you need to do more research into JSON deserializing. You are demonstrating a severe lack of knowledge – maccettura Mar 27 '18 at 19:51
  • in that case. the error is "Newtonsoft.Json.JsonSerializationException: 'Error converting value "id" to type 'TalkBotAI.City+values'. Path '', line 1, position 8.'" @dbc –  Mar 27 '18 at 20:01

1 Answers1

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.

maccettura
  • 10,514
  • 3
  • 28
  • 35
  • 2
    If the file is long (which it is, at 1.8milion lines), I would not do this. I would instead stream directly. See https://www.newtonsoft.com/json/help/html/Performance.htm#MemoryUsage as well as [Can Json.NET serialize / deserialize to / from a stream?](https://stackoverflow.com/a/17788118). – dbc Mar 27 '18 at 20:02
  • @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 – maccettura Mar 27 '18 at 20:06
  • 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. –  Mar 27 '18 at 20:06
  • @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. – dbc Mar 27 '18 at 20:07
  • @HelpIsNeeded your class can just be those properties. You dont have to have a POCO that matches the entire object – maccettura Mar 27 '18 at 20:07
  • Alright, i swapped "City" to "City.Values" and that does the work^^ –  Mar 27 '18 at 20:10