0

In my Xamarin forms project i parse JSON data which loaded from a file. Anyways, the JSON data is 1000% valid as i can parse it in other places it and it's already used by a Native Android Application (Java) and PHP without any problem, but somehow Xamarin fails to understands it, and it gives me this error:

Unhandled Exception:

Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: {. Path 'category', line 1, position 26.

Now This is my JSON data:

{"response":1,"category":{"2":{"n":"V\u00e9hicules","d":"C-Vehicules","i":"icon-car","l":{"3":{"n":"Voitures","d":"Voitures"},"4":{"n":"Motos","d":"Motos"},"6":{"n":"Nautisme","d":"Nautisme"},"7":{"n":"\u00c9quipement Auto","d":"Equipement-Auto"},"8":{"n":"\u00c9quipement Moto","d":"Equipement-Moto"},"10":{"n":"Equipement Nautisme","d":"Equipement-Nautisme"}}},"3":{"n":"Immobilier","d":"C-Immobilier","i":"icon-office","l":{"15":{"n":"Ventes immobili\u00e8res","d":"Ventes-immobilieres"},"16":{"n":"Locations","d":"Locations"},"17":{"n":"Bureaux - Commerces","d":"Bureaux-Commerces"}}},"1":{"n":"Emploi","d":"C-Emploi","i":"icon-bag","l":{"1":{"n":"Offres d'emploi","d":"Offres-d--emploi"}}},"9":{"n":"Services","d":"C-Services","i":"icon-service","l":{"18":{"n":"Prestations de services","d":"Prestations-de-services"},"19":{"n":"Cours particuliers","d":"Cours-particuliers"}}},"4":{"n":"Vacances","d":"C-Vacances","i":"icon-plane","l":{"20":{"n":"Locations de vacances","d":"Locations-de-vacances"},"21":{"n":"Chambres d'h\u00f4tes","d":"Chambres-d--hotes"},"22":{"n":"Campings","d":"Campings"}}},"7":{"n":"Loisirs","d":"C-Loisirs","i":"icon-music","l":{"24":{"n":"CD Musique","d":"CD-Musique"},"23":{"n":"DVD Films","d":"DVD-Films"},"27":{"n":"Jeux - Jouets","d":"Jeux-Jouets"},"25":{"n":"Livres","d":"Livres"},"26":{"n":"Sports","d":"Sports"}}},"5":{"n":"Maison","d":"C-Maison","i":"icon-house","l":{"36":{"n":"Accessoires","d":"Accessoires"},"28":{"n":"Ameublement","d":"Ameublement"},"30":{"n":"Arts de la table","d":"Arts-de-la-table"},"38":{"n":"B\u00e9b\u00e9","d":"Bebe"},"37":{"n":"Bijoux - Montres","d":"Bijoux-Montres"},"33":{"n":"Bricolage","d":"Bricolage"},"35":{"n":"Chaussures","d":"Chaussures"},"31":{"n":"D\u00e9coration","d":"Decoration"},"29":{"n":"Electrom\u00e9nager","d":"Electromenager"},"32":{"n":"Linge de maison","d":"Linge-de-maison"},"34":{"n":"V\u00eatements","d":"Vetements"}}},"6":{"n":"Multim\u00e9dia","d":"C-Multimedia","i":"icon-phone","l":{"40":{"n":"Consoles - Jeux vid\u00e9o","d":"Consoles-Jeux-video"},"41":{"n":"Image - Son","d":"Image-Son"},"39":{"n":"Informatique","d":"Informatique"},"42":{"n":"T\u00e9l\u00e9phonie","d":"Telephonie"}}},"8":{"n":"Mat\u00e9riel professionnel","d":"C-Materiel-professionnel","i":"icon-tool","l":{"47":{"n":"Equipements","d":"Equipements"},"43":{"n":"Mat\u00e9riel agricole","d":"Materiel-agricole"},"45":{"n":"Mat\u00e9riel BTP","d":"Materiel-BTP"},"46":{"n":"Outillage","d":"Outillage"},"48":{"n":"Restauration - caf\u00e9","d":"Restauration-cafe"},"44":{"n":"Transport","d":"Transport"}}}}}

And this is the line where the exception occures:

var general = JsonConvert.DeserializeObject<GeneralConfig>(config);

Update:

I didn't put the complete JSON file, i simplified it in the example above by remove other objects next to category, The reason why i simplified it is because SO won't let put the whole JSON contents and the error message clearly shows that the problem is in here:

 "category":{"2":{"n":"V\u00e9hicules",

Update:

Here's the code that reads the JSON:

namespace HelloWorldApp
{
class Config
{

    string config = "";

    public Config()
    {
        var assembly = typeof(MainPage).GetTypeInfo().Assembly;
        //Stream stream = assembly.GetManifestResourceStream("HelloWorldApp.Resources.configs.json");
        string[] resources = Assembly.GetExecutingAssembly().GetManifestResourceNames();
        foreach (string resource in resources)
        {
            if (resource.EndsWith(".json"))
            {
                Stream stream = assembly.GetManifestResourceStream(resource);
                if (stream != null)
                {
                    using (var reader = new System.IO.StreamReader(stream))
                    {
                        config = reader.ReadToEnd();
                    }
                }
            }
        }

    }

    public void getCategory(int id)
    {
        var general = JsonConvert.DeserializeObject<GeneralConfig>(config);
        var category = general.category;
        var cats = JsonConvert.DeserializeObject<List<CategoryConfig>>(config);
        foreach (var item in cats)
        {
            Console.WriteLine("Cat: " + item.n);
        }
    }

And here's General Config:

class GeneralConfig
{
    public string category { get; set; }
    public int city { get; set; }
    public string brand { get; set; }
    public int model { get; set; }
}

Error 2:

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'HelloWorldApp.CategoryConfig' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.

To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array. Path 'category', line 1, position 26.

user700390
  • 2,287
  • 1
  • 19
  • 26
4 R4C81D
  • 192
  • 13
  • I use: http://jsoneditoronline.org/ and the same JSON is parsed in Java perfectly, i don't think C# has it's own JSON rules, or is this the case? – 4 R4C81D Jun 14 '17 at 13:21
  • @GeraldVersluis strange, JSONLint and [Curious Concept](https://jsonformatter.curiousconcept.com/) say its valid. –  Jun 14 '17 at 13:21
  • json2csharp say no – Alessandro Caliaro Jun 14 '17 at 13:23
  • 1
    It can, and there are no different rules. JSON errors mean that the *string* has a problem. At the very least, this string contains escape sequences that shouldn't be there. There's no reason to use escape sequences in a *Unicode* string – Panagiotis Kanavos Jun 14 '17 at 13:23
  • @PanagiotisKanavos There're no escape sequences in the JSON text, \u00e is a unicode translation to the french letter é – 4 R4C81D Jun 14 '17 at 13:27
  • Please post the **actual** string. C# strings can't have double quotes without escaping. They don't need escape sequences either. It's impossible to help unless you post the *actual* data – Panagiotis Kanavos Jun 14 '17 at 13:27
  • The JSON data does not have to be typed in as source code, it coul dhave come from a text file or web call – user700390 Jun 14 '17 at 13:34
  • @4R4C81D Can you post the class definition for `GeneralConfig` – user700390 Jun 14 '17 at 13:35
  • @4R4C81D I'll have to repeat. Please post a *reproducible* example with the *code* that demonstrates the problem. `JsonConvert.DeserializeObject("{\"response\":1,\"category\":{\"a\":{\"n\":\"Véhicules\",\"d\":\"C-Vehicules\",\"i\":\"icon-car\"}}}")` works just fine. So does `JsonConvert.DeserializeObject("{'response':1,'category':{'a':{'n':'Véhicules','d':'C-Vehicules','i':'icon-car'}}}")` – Panagiotis Kanavos Jun 14 '17 at 13:39
  • Also works: `JsonConvert.DeserializeObject("{'response':1,'category':'C-V\u00e9hicules'}")`. I suspect that the code that *generates* the string emits the characters of the escape sequence instead of the actual Unicode character – Panagiotis Kanavos Jun 14 '17 at 13:42
  • Ok, i'll try to replace u000e9 by é and see what happens, while compiling i'll post the complete code of the method + GeneralConfig. – 4 R4C81D Jun 14 '17 at 13:44
  • Please show the definition of the `GeneralConfig` class – Gerald Versluis Jun 14 '17 at 13:49
  • Updated sir, check the question. – 4 R4C81D Jun 14 '17 at 13:52
  • @PanagiotisKanavos the OP is using the generic deserialization method. You need the class definitions to understand why it is not parsing properly. – user700390 Jun 14 '17 at 14:09
  • @user700390 the error complains about the text itself. And that *still* is neither a Unicode character nor a valid C# string. – Panagiotis Kanavos Jun 14 '17 at 14:14
  • @PanagiotisKanavos The error points to position 26 which is `{"2"` as the first member of a key/value dictionary – user700390 Jun 14 '17 at 14:17
  • @4R4C81D Please post a reproducible example, not your Config class code. A simple one-line like those I posted should be enough. An assembly string resource *doesn't* need escape sequences to represent Unicode charactes anyway. Most likely, you've stored an invalid Json string in the resource. It's impossible to tell though without an actual example – Panagiotis Kanavos Jun 14 '17 at 14:19
  • @user700390 which is about the character, not the property. The content will be ignored without an error if there is no matching property. At this point, we still don't have the string. We have an error about the sting's contents – Panagiotis Kanavos Jun 14 '17 at 14:21
  • @PanagiotisKanavos It is self evident from the available code, which tries to interpret `category` as a string, whilst it is clearly a more complex object. – user700390 Jun 14 '17 at 14:23
  • > Sorry the poor english I see you have some properties in your json that are begining with a number as property name... It can't be. Can we see your GeneralConfig class? – Diego Rafael Souza Jun 14 '17 at 13:45

3 Answers3

1

Well, for starters, you've answered your own question. Xamarin is a runtime, how or why would it need to "understand" JSON?

The problem is coming from Newtonsoft.Json.JsonReaderException. As shown by the exceptions message, you have invalid JSON.

The problem absolutely is the Unicode symbol at position 26: V\u00e9hicules.

This answer should help: Serializing foreign languages using JSON.Net

user9993
  • 5,833
  • 11
  • 56
  • 117
1

Your class appears to be defined incorrectly.

category is clearly not a string based on the JSON data.

I think you need to define a container object such as:

public class GeneralConfig
{
    int response;
    Dictionary<string,CategoryConfig> category;
}

Also you should only be calling JsonConvert.DeserializeObject<GeneralConfig>(), you should not be making the second call.

user700390
  • 2,287
  • 1
  • 19
  • 26
  • Category is an object that has multiple sub-objects, what type should i declare it? – 4 R4C81D Jun 14 '17 at 13:53
  • You need to define custom classes for the dictionary items, then the GeneralConfig is going to need to contain some kind of Dictionary as a member. – user700390 Jun 14 '17 at 13:56
  • Oh that makes sense, i have a Category object, let me try and get back, 1 min. – 4 R4C81D Jun 14 '17 at 13:57
  • I think this is the right path, but it gives me this error: (see updated question) – 4 R4C81D Jun 14 '17 at 13:59
  • You need to come to a better understanding of how the data is structured coming into your application. If you are not able to make it work at this point I would consider producing a MCVE – user700390 Jun 14 '17 at 14:04
  • Okay, i'm new to C# and this way of PARSING json is really annoying, can you please give me a complete example of how to get a category name right from my JSON? – 4 R4C81D Jun 14 '17 at 14:09
  • This way of parsing is really much easier, but you need to understand the data first. Based on the JSON you have provided I don't see any JSON arrays. Can you produce a smaller example of the JSON data that can reproduce the problem? – user700390 Jun 14 '17 at 14:11
  • Here is it sir: {"response":1,"category":{"2":{"n":"V\u00e9hicules","d":"C-Vehicules","i":"icon-car","l":{"3":{"n":"Voitures","d":"Voitures"}}}}} – 4 R4C81D Jun 14 '17 at 14:19
  • A property mismatch would simply leave the property empty, it wouldn't raise an error – Panagiotis Kanavos Jun 14 '17 at 14:24
  • @PanagiotisKanavos In JSON a string needs to start with a quotation mark ", not an opening curly brace {, the definition in code must be consistent with the type of the underlying data. – user700390 Jun 14 '17 at 14:25
  • @4R4C81D Based on your JSON snippet you have further nesting of your classes... Your `category` contains `2` which contains `l` and which in turn contains "3" ,are you sure this is intended, should "3" be at a different level of nesting? – user700390 Jun 14 '17 at 14:26
  • Yes this is intended i'd say, 1, 2 and 3 are ID's – 4 R4C81D Jun 14 '17 at 14:29
  • @4R4C81D Based on what you have written, I think you are misunderstanding my statement. Your JSON places these items at different levels in the hierarchy, based on your statement that each is an ID, they should be at the same level in the hierarchy. – user700390 Jun 14 '17 at 15:48
  • Well i understand that my JSON isn't perfect but i have no choice but to be able to parse it and extract the data i want as it may be coming from an external API later on, which i have no control over. – 4 R4C81D Jun 15 '17 at 02:01
  • i could finaly extract data from the JSON thanks to the points you highlighted, so i'll chose this answer, Thank you. – 4 R4C81D Jun 15 '17 at 02:21
-2

C# doesn't have properties that start with a number. For example "2": cannot be deserialized into a property.

Also your json has the escape character `\u00' in numerous places, perhaps this is also causing an issue.

Amir Vakili
  • 132
  • 1
  • 8