使用 Newtonsoft.JSON 在 C# 中的泛型方法中的 DeserializeObject<T>(string s) 不起作用

Posted

技术标签:

【中文标题】使用 Newtonsoft.JSON 在 C# 中的泛型方法中的 DeserializeObject<T>(string s) 不起作用【英文标题】:DeserializeObject<T>(string s) in generic method in C# using Newtonsoft.JSON is not working 【发布时间】:2017-06-07 04:55:45 【问题描述】:

目前我只是将 json 字符串返回到调用 Test1() 的相应文件并在那里反序列化为 ResponseClass r = JsonConvert.DeserializeObject(response_json) 发送部分我忘记创建一个类 [Serializable]。它现在工作正常。

第 1 部分:

public class Movie

    public string Name  get; set; 
    public string Description  get; set; 
    public string Classification  get; set; 
    public string Studio  get; set; 
    public DateTime? ReleaseDate  get; set; 
    public List<string> Genres get; set; 



public class ResponseClass

    public string SuccessStatus get; set; 
    public string next_link  get; set; 



private void Test1<T,Q>()

    string json = @"
      'Name': 'Bad Boys',
      'ReleaseDate': '1995-4-7T00:00:00',
      'Genres': [
        'Action',
        'Comedy'
      ]
    ";


   //Here making network call with above json and getting correct response_josn
    Q response_obj = JsonConvert.DeserializeObject<Q>(reponse_json);
    print(response_obj);

我在按钮点击时调用 Test1() 如下:

Test1<Movie, ResponseClass>();

对于上面的示例,我将打印日志作为 ClassName+Movie (T FullName)。 我想将字符串反序列化到该类中。如何实现?

第 2 部分:如果我的课程为:

[Serializable]
public class Movie

    public string Name;
    public string Description;
    public string Classification;
    public string Studio;
    public DateTime ReleaseDate;
    public SubClass subClass;
    public List<SubClass> lsubclass;

[Serializable] //This was the mistake. 
public class SubClass

    public string a;
    public string b;
    public List<string> ReleaseCountries;


private Movie createValidMovieJson()

    Movie m = new Movie();

    SubClass sc = new SubClass();
    sc.a = "aaa";
    sc.b = "bbb";
    sc.ReleaseCountries = new List<string>();
    sc.ReleaseCountries.Add("Japan");
    sc.ReleaseCountries.Add("India");
    List<SubClass> lsC = new List<SubClass>();
    lsC.Add(sc);
    lsC.Add(sc);

    m.Name = "Bad Boys";
    m.Studio = "Pixa";
    m.subClass = sc;
    m.lsubclass = lsC;
    Debug.Log(JsonUtility.ToJson(m));  // value n log = "Name":"Bad Boys","Description":"","Classification":"","Studio":"Pixa"
    return m;

JsonUtility 在使用ToJson() 后返回空值代替子类,如上函数所示。

【问题讨论】:

你怎么称呼Test1? 已编辑问题@David L 您应该在 Unity 中使用 JsonUtility。让我知道这可以解决您的问题。 我刚刚将 T m = JsonConvert.DeserializeObject&lt;T&gt;(json); 替换为 T m = JsonUtility.FromJson&lt;T&gt;(json); 它给出了错误 ArgumentException: JSON parse error: Missing a name for object member。 @djkp 不要忽略答案。如果它起作用了,你说它起作用了,或者它没有解释发生了什么。 【参考方案1】:

根据您添加的屏幕截图,我认为您希望能够将反序列化类型视为电影。这是实现这一目标的方法:

var movie = JsonConvert.DeserializeObject<Movie>(json);

目前,您的反序列化对象被视为 T 类型 - 这可以是任何类型,因为您的方法没有泛型类型约束。

【讨论】:

我的问题是如何使它适用于如上所示的通用方法 好的,在这种情况下,您的泛型方法应该有一个返回类型 T 并且应该返回反序列化的对象。然后你可以调用这样的方法: var movie = Test1();【参考方案2】:

就像我在评论部分说的,JsonUtility 应该这样做。

我刚刚替换了 T m = JsonConvert.DeserializeObject(json);与 T m = JsonUtility.FromJson(json);它给出了一个错误 ArgumentException:JSON 解析错误:缺少对象成员的名称。

您的 json 对于 JsonUtility 无效。我相信您使用的是' 而不是"。这就是您收到此错误的原因。

使用下面的函数生成一个有效的json:

void createValidMovieJson()

    Movie m = new Movie();
    m.Name = "Bad Boys";
    m.ReleaseCountries = new List<string>();
    m.ReleaseCountries.Add("Japan");

    m.Studio = "Pixa";
    Debug.Log(JsonUtility.ToJson(m));

你会得到:

 "Name":"Bad Boys","Description":"","Classification":"","Studio":"Pixa","ReleaseCountries":["Japan"]

当ecaped进行测试时,你会得到:

\"Name\":\"Bad Boys\",\"Description\":\"\",\"Classification\":\"\",\"Studio\":\"Pixa\",\"ReleaseCountries\":[\"Japan\"]

要使JsonUtility 起作用,您必须将[Serializable] 添加到类并从它们的类变量中删除 get; set;

如果您的目标是将任何 json 转换为任何数据类型,那么您必须返回泛型类型,然后使用 Convert.ChangeType 将其转换为该类型。

它应该看起来像这样:

// Use this for initialization
void Start()

    string json = "\"Name\":\"Bad Boys\",\"Description\":\"\",\"Classification\":\"\",\"Studio\":\"Pixa\",\"ReleaseCountries\":[\"Japan\"]";

    Movie movie = Load<Movie>(json);
    print(movie.Name);


[Serializable]
public class Movie

    public string Name;
    public string Description;
    public string Classification;
    public string Studio;
    public DateTime? ReleaseDate;
    public List<string> ReleaseCountries;


private T Load<T>(string json)

    object resultValue = JsonUtility.FromJson<T>(json);
    return (T)Convert.ChangeType(resultValue, typeof(T));

【讨论】:

OP 特别要求提供通用解决方案。也就是说,这个问题还不清楚,无法正确回答。 @DavidL 这被标记为 Unity 问题。确保在下次回答或否决答案之前阅读标签。 1.Unity中不能使用JSON.Net。由于 Unity 中的 .NET 版本差异。 2.Unity有一个pad版的JSON.Net,但是这个问题不用买任何东西就可以解决。 3.JsonUtility 应该使用,因为它内置于 Unity 中,并且在大多数情况下比 JSON.Net 更快。 3.至于泛型,Test1&lt;T&gt;()函数采用泛型。同样,T m = JsonUtility.FromJson&lt;T&gt;(json);。我认为这就是OP的意思。编码愉快! 感谢您提供 Unity 中 JSON.net 的背景知识。这是非常有用的。我已经删除了与它相关的评论。但我不同意您在将强制转换隐藏在泛型方法中时如何认为这是在利用泛型。 您看到的Movie movie = (Movie)(object)m; 演员表仅用于测试目的。显示班级的姓名。这不是答案的一部分。这只是为了向 OP 展示 JsonUtility 能够反序列化该类。问题中的 main 问题是 OP 无法将 json 反序列化为类。我的解决方案只是告诉 OP 使用 JsonUtility,它解释了他在反序列化时出错的许多原因。 很好,但这限制了我只能在 Test1 中使用电影类来键入 cast ,如果我有多个类并且我想对每个类进行一般的类型转换怎么办?这是我的问题的重点之一。否则,安迪·吉布森 (Andy Gibson) 的 cmets 解决方案对我来说效果很好。

以上是关于使用 Newtonsoft.JSON 在 C# 中的泛型方法中的 DeserializeObject<T>(string s) 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

C#中使用Newtonsoft.Json序列化和反序列化自定义类对象

如何使用 C# 进行条件序列化 - NewtonSoft.Json

C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json

C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json

C# unity (发布到安卓端中使用)解析json字符串—使用微软官方的包Newtonsoft.Json

C# 程序集绑定重定向 - Newtonsoft.Json