user11214193
user11214193

Reputation:

Unexpected character encountered while parsing value from API

Having a bit of an issue with an API which is returning some Json data. Here is the sample from the data:

"player": {
    "_id": "ID",
    "achievements": {
    "achievementsOneTime": [
        "supersmash_tinman_challenge",
        [],
        "blitz_kill_without_kit",
        "supersmash_too_easy",
        "supersmash_supremacy",
        "blitz_first_blood",
        "blitz_full_inventory",
        "supersmash_two_for_one",
        "skywars_max_perk",
        "skywars_legendary",
        "skywars_portal_game",
        "skywars_speed_runner",
        "skywars_trolol",
        "skywars_sniper",
        "truecombat_ender_dragon",
        "skywars_solo_warrior",
        "speeduhc_golden_apple",
        "speeduhc_melon_smasher",
        "speeduhc_enchanted_book",
        "speeduhc_enchanted_armor",
    ]

As you may see there is a random [], in the achievementsOneTime. This is throwing the error:

Unexpected character encountered while parsing value: [.

when trying to deserialize it in my code:

    //Create the request
    var client = new RestClient("https://api.hypixel.net/");
    var request = new RestRequest($"player?key={_apiKey}&name={name}", Method.GET);

    //Get the response and Deserialize
    var response = client.Execute(request);
    var responseDeserialized = JsonConvert.DeserializeObject<GetPlayerData>(response.Content);

Is there any way of ignoring that [],?

Sorry I'm not too sure really where to go

Any help will be appreciated.

Thanks

Upvotes: 0

Views: 1460

Answers (2)

Nathanael Mathis
Nathanael Mathis

Reputation: 1

You should avoid mixing types. The issue is almost certainly that the field/property that corresponds to "achievementsOneTime" in GetPlayerData is a string[] or List<string> etc. In that case [], would be invalid. Also, I notice that the array ends in a comma, this won't break in Newtonsoft, but that is technically invalid JSON.

I was able to get a similar error with:

JsonConvert.DeserializeObject<string[]>("[\"1\", [], \"2\"]")

Error: Unexpected character encountered while parsing value: [. Path '[0]', line 1, position 7

Upvotes: 0

Kaushal
Kaushal

Reputation: 1359

First you should check if any issue with API response. Its not common (and not recommended) to have mixed types in same field.

Ideally API should vent fields bound to single type and defined semantic.

If fixing API is not possible, then following are options

Option 1:

Deserialize achivementOneTime in object field. Based on type of value, you can execute different logic. If you want to use only string value, check type to be string before using it.

Sample code:

public class Program
{
    public static void Main()
    {
       string jsonData = "{ \"achievementsOneTime\": [ \"supersmash_tinman_challenge\", [], \"blitz_kill_without_kit\"] }";
       var responseDeserialized = JsonConvert.DeserializeObject<Achievements>(jsonData);
       Console.WriteLine("Deserialized response is ::");

       int index = 0;
       foreach (var item in responseDeserialized.achievementsOneTime)
       {
          PrintAchievementsOneTime(item, index);
          index++;
       }
     }

     private static void PrintAchievementsOneTime(Object achievementsOneTime, int index) {
         Console.WriteLine("Item at index " + index + " type is : " + achievementsOneTime.GetType().Name + ". Value is : " + achievementsOneTime);
    }
}

public class Achievements {
     public Object[] achievementsOneTime;
}

Output :

Deserialized response is ::
Item at index 0 type is : String. Value is : supersmash_tinman_challenge
Item at index 1 type is : JArray. Value is : []
Item at index 2 type is : String. Value is : blitz_kill_without_kit

Option 2

Other similar option is to implement AchievementsOneTimeConverter derived from JsonConverter. Override ReadJson method to ignore JToken whose tpye is not string. Add JsonConverter attribute on achievementsOneTime.

public class Achievements2 {
    [JsonConverter(typeof(AchievementsOneTimeConverter))]
    public List<string> achievementsOneTime;
}

public class AchievementsOneTimeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object[]);
    }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            List<string> result = new List<string>();
            foreach (JToken token in JArray.Load(reader).Children())
            {
                if (token.Type == JTokenType.String)
                {
                    result.Add(token.ToString());
                }
            }

            return result;
         }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Output will only have string

Deserialized response is ::
Item at index 0 type is : String. Value is : supersmash_tinman_challenge
Item at index 1 type is : String. Value is : blitz_kill_without_kit

Upvotes: 1

Related Questions