从API解析值时遇到意外字符

时间:2019-03-16 20:42:19

标签: c# json

返回一些Json数据的API有点问题。 这是数据示例:

"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",
    ]

您可能会看到[]中有一个随机的achievementsOneTime。这会引发错误:

  

解析值[。时遇到意外字符。

当尝试在我的代码中反序列化时:

    //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);

有什么办法可以忽略[],吗?

对不起,我不太确定该去哪里

任何帮助将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:1)

首先,您应该检查API响应是否存在任何问题。在同一字段中具有混合类型并不常见(也不建议)。

理想情况下,API应该释放绑定到单一类型和已定义语义的字段。

如果无法修复API,则可以选择以下选项

选项1:

在对象字段反序列化achivementOneTime。根据值的类型,您可以执行不同的逻辑。如果只想使用字符串值,请在使用之前将类型检查为字符串。

示例代码:

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;
}

输出:

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

选项2

其他类似的选项是实现从JsonConverter派生的AchievementsOneTimeConverter。 重写ReadJson方法可忽略其tpye不是字符串的JToken。 在AchievementOneTime上添加JsonConverter属性。

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();
    }
}

输出将仅包含字符串

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

答案 1 :(得分:0)

您应避免混合使用类型。问题几乎可以肯定是,与GetPlayerData中的“ achievementsOneTime”相对应的字段/属性是string[]List<string>等。在这种情况下,[]无效。另外,我注意到该数组以逗号结尾,在Newtonsoft中不会中断,但这在技术上是无效的JSON。

我能够通过以下方式得到类似错误:

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

错误:解析值[时遇到意外字符。路径“ [0]”,第1行,位置7