Reputation:
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
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
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