使用JsonConvert.DeserializeObject或JObject.Parse在C#中将类反序列化为字典

时间:2019-02-21 17:14:29

标签: c# json json.net

我正在Asp.Net Core 2.2中做一个小型的API项目,该项目将提取国家,货币,语言等数据(静态数据)。

假设我的JSON格式如下:

{
  "data": {
    "countries": [
      {
        "translatedName": "Ascension Island",
        "translations": [
          {
            "languageCode": "bg-BG",
            "translatedName": "Остров Възнесение"
          },
          {
            "languageCode": "cs-CZ",
            "translatedName": "Ascension"
          }
        ]
   }
}

我只想在data标记对象中获取JSON文本并将其反序列化为此类:

class Country
{
      public string TranslatedName { get; set; }

      public Dictionary<string, string> Translations { get; set; 
} 

因此,我们的想法是字典的键将是languageCode,而值将是translationName。

data对象将以我得到的任何形式的响应出现,而对于其他部分,它可能会更改。可能是data -> countriesdata -> languagesdata -> currencies等。

因此解析的方法如下所示;

public T Parse<T>(string fieldName, string json)
{

}

fieldName将确定在data键之后的第二个子名称,因此结构将始终为data -> fieldName。我可以说string.Replace(...)来替换JSON中未使用的( data key )部分,但是我在想是否有更好的方法!

第二个问题是我如何反序列化字典的翻译?

我尝试在方法中执行以下操作:

public T Parse<T>(string fieldName, string json)
{
    return JObject.Parse(json)[fieldName].ToObject<T>();
}

所以,如果我使用这种方法:

var countries = Parse<List<Country>>("countries", ....); //it fails due to the fact it does not know how to convert translations to dictionary

我真的很感谢您的帮助:

2 个答案:

答案 0 :(得分:0)

我在这里为您创建了此功能,进行了测试,并可以与您的json字符串一起使用。

var json = "{ data: { countries: [{ translatedName: 'Ascension Island', translations: [{ languageCode: 'bg-BG', translatedName: 'Остров Възнесение'}, { languageCode: 'cs-CZ',translatedName: 'Ascension' }]}]} }";
List<Country> countries = Parse<List<Country>>(json, "data.countries");
public static T Parse<T>(string json, string key)
{
    var rss = JObject.Parse(json);
    JToken jtoken = null;
    foreach (var k in key.Split('.'))
    {
        if (jtoken != null)
            jtoken = jtoken[k];
        else jtoken = rss[k];

    }

    return jtoken.ToObject<T>();
}

答案 1 :(得分:-1)

最后我可以解决问题:

对于@Camilo建议的第一个问题,我创建了一个包装器。
第二次,我创建了一个自定义JsonConverter,如下所示为我完成了工作。

internal class TranslationsToDictionaryObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(List<CountryInfoModel>).IsAssignableFrom(objectType) 
            || typeof(List<CurrencyInfoModel>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        Dictionary<string, string> dict = new Dictionary<string, string>();
        try
        {
            foreach (var item in token)
            {
                dict.Add(item["languageCode"].ToString(), item["translatedName"].ToString());
            }
        }
        catch
        {
            // ignored
        }

        return dict;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
    }
}

之后,模型将如下所示:

[Serializable]
public class CountryInfoModel 
{
    public int BwinId { get; set; }

    public string TranslatedName { get; set; }

    public string TwoLetterCode { get; set; }

    public bool LoginAllowed { get; set; }

    public bool RegistrationAllowed { get; set; }


    [JsonConverter(typeof(TranslationsToDictionaryObjectConverter))]
    public Dictionary<string, string> Translations { get; set; }
}