不创建类的情况下反序列化JSON响应

15

从 API 调用结果中,我需要处理大量的 JSON。

目前我有这个:

Object convertObj = JsonConvert.DeserializeObject(responseFromServer);

我知道我可以做这样的事情

Movie m = JsonConvert.DeserializeObject<Movie>(responseFromServer);

然后像这样使用它

m.FieldName
m.AnotherField
//etc

理想情况下,我希望能做类似于

var itemName = convertObj["Name"];

获取列表中第一个项目的第一个Name值,是否可行?还是必须创建一个类来反序列化?

我不想创建这个类的原因是我不是该API的所有者,字段结构可能会发生更改。

编辑。

好的,既然看起来创建类是最佳方法,但有没有办法将JSON反序列化为列表?

var sessionScans = new List<SessionScan>();
sessionScans = JsonConvert.DeserializeObject<SessionScan>(responseFromServer);

抱怨无法将SessionScan转换为通用列表。


你可以使用 Dynamic,但不建议这样做。 - Mohit S
可能是将JSON反序列化为C#动态对象的重复问题?的一个副本。 - Davatar
@MohitShrivastava 为什么不推荐呢? - Jim
@Jim,动态类型的问题在于它经常隐藏了编译时会暴露出来的错误。这些错误只有在运行时才会显现出来,这当然使得它们更难以被检测到。 - Mohit S
@MohitShrivastava 是的,我完全同意你的观点。另一方面,问题本质上是“如何在不创建类的情况下反序列化JSON响应”。 - Jim
7个回答

18

不需要使用dynamic,你可以直接使用JToken,它已经实现了你所期望的功能:

var json = @"
    {
        ""someObj"": 5
    }
";
var result = JsonConvert.DeserializeObject<JToken>(json);
var t = result["someObj"]; //contains 5

12

使用.NET 6,可以按以下方式完成此操作:

using System.Text.Json;
using System.Text.Json.Nodes;

string jsonString = @"some json string here";

JsonNode forecastNode = JsonNode.Parse(jsonString)!;

int temperatureInt = (int)forecastNode!["Temperature"]!;
Console.WriteLine($"Value={temperatureInt}");

//for nested elements, you can access as below
int someVal = someNode!["someParent"]["childId"]!.ToString();

有关更多示例,请参阅 Microsoft 文档页面 - 使用初始化器创建对象,对DOM进行更改,反序列化JSON负载的子节


5
您可以尝试使用 JObject.Parse
dynamic convertObj = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

string name = convertObj.Name;
string address = convertObj.Address.City;

2
以下示例可以使用NewtonSoft.JsonDeserializeAnonymousType方法将JSON反序列化为匿名对象列表。
var json = System.IO.File.ReadAllText(@"C:\TestJSONFiles\yourJSONFile.json");
var fooDefinition = new { FieldName = "", AnotherField = 0 }; // type with fields of string, int
var fooListDefinition = new []{ fooDefinition }.ToList();

var foos = JsonConvert.DeserializeAnonymousType(json, fooListDefinition);

1

我曾经在使用未知的API时遇到了这个问题,然后我决定采用这种方法来解决这个问题,我在这里写下了我的测试案例:

            [TestMethod]
        public void JsonDocumentDeserialize()
        {
            string jsonResult = @"{
""status"": ""INTERNAL_SERVER_ERROR"",
    ""timestamp"": ""09-09-2019 11:00:24"",
    ""message"": ""documentUri is required.""
}";

            var jDoc = JsonDocument.Parse(jsonResult);
            if (jDoc.RootElement.TryGetProperty("message", out JsonElement message))
            {
                Assert.IsTrue(message.GetString() == "documentUri is required.");
            }
        }

这对我很有用,因为我首先想找到一种在Azure Function HTTPTrigger中使用动态类型的方法。但我发现这种方法最有用和最稳健。

Microsoft 参考文献


0

0

使用Newtonsoft.Json

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

var json = "[{'a':'aaa','b':'bbb','c':'ccc'},{'a':'aa','b':'bb','c':'cc'}]";
var ja = (JArray)JsonConvert.DeserializeObject(json);
var jo = (JObject) ja[0];
Console.WriteLine(jo["a"]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接