c# - JRaw SelectToken 返回 null
问题描述
我在 .Net core 2.0 中使用 Newtonsoft.Json 11.0.2。
如果我使用 JObject,我会SelectToken
喜欢这样:
JObject.Parse("{\"context\":{\"id\":42}}").SelectToken("context.id")
退货
42
但是,如果我使用 JRaw,我会为同一路径获得 null 吗?
new JRaw("{\"context\":{\"id\":42}}").SelectToken("context.id")
返回
空值
由于我的代码是如何设置的,我的模型已经在 JRaw 中,将它转换为 JObject 只是为了选择这个标记似乎浪费了 RAM(这个调用在热路径上)。
更新 好的,我的实际数据来自一个模型,其中只有一个属性是 JRaw,所以我需要类似下面的东西才能工作:
JsonConvert.DeserializeObject<Dictionary<string, JRaw>>(
"{\"a\":{\"context\":{\"id\":42}}}")["a"].SelectToken("context.id")
以上再次返回null。
解决方案
标题可能有点误导,但基本上 OP 需要的是一种在JRaw
不消耗太多内存的情况下解析现有(和大型)对象的方法。
我进行了一些测试,并且能够使用JsonTextReader
.
我不知道 OP 的 json 字符串的确切结构,所以我假设是这样的:
[
{
"context": {
"id": 10
}
},
{
"context": {
"id": 20
}
},
{
"context": {
"id": 30
}
}
]
结果将是一个具有 id 值 (10, 20, 30) 的整数数组。
解析方法
所以这是将JRaw
对象作为参数并提取 Ids 的方法,使用JsonTextReader
.
private static IEnumerable<int> GetIds(JRaw raw)
{
using (var stringReader = new StringReader(raw.Value.ToString()))
using (var textReader = new JsonTextReader(stringReader))
{
while (textReader.Read())
{
if (textReader.TokenType == JsonToken.PropertyName && textReader.Value.Equals("id"))
{
int? id = textReader.ReadAsInt32();
if (id.HasValue)
{
yield return id.Value;
}
}
}
}
}
在上面的示例中,我假设只有一种类型的对象具有 id 属性。
还有其他方法可以提取我们需要的信息 - 例如,我们可以检查令牌类型和路径,如下所示:
if (textReader.TokenType == JsonToken.Integer && textReader.Path.EndsWith("context.id"))
{
int id = Convert.ToInt32(textReader.Value);
yield return id;
}
测试代码
出于测试目的,我创建了以下与上述 json 结构匹配的 C# 类:
public class Data
{
[JsonProperty("context")]
public Context Context { get; set; }
public Data(int id)
{
Context = new Context
{
Id = id
};
}
}
public class Context
{
[JsonProperty("id")]
public int Id { get; set; }
}
创建一个 JRaw 对象并提取 Id:
class Program
{
static void Main(string[] args)
{
JRaw rawJson = CreateRawJson();
List<int> ids = GetIds(rawJson).ToList();
Console.Read();
}
// Instantiates 1 million Data objects and then creates a JRaw object
private static JRaw CreateRawJson()
{
var data = new List<Data>();
for (int i = 1; i <= 1_000_000; i++)
{
data.Add(new Data(i));
}
string json = JsonConvert.SerializeObject(data);
return new JRaw(json);
}
}
内存使用情况
使用 Visual Studio 的诊断工具,我拍摄了以下快照,以检查内存使用情况:
- 快照 #1 是在控制台应用程序开始时拍摄的(正如预期的那样,内存不足)
- 快照 #2 是在创建 JRaw 对象后拍摄的
JRaw rawJson = CreateRawJson();
- 快照 #3 是在提取 ID 后拍摄的
列表 ids = GetIds(rawJson).ToList();
推荐阅读
- c++ - 使用参数不明确的函数
- javascript - `this` 访问对象属性
- javascript - 从其他 Web 服务器页面以 javascript 保存文本
- android - 滚动视图不滚动android工作室
- javascript - 为什么非英文字母在 HTML 中呈现乱码?
- ios - 你如何改变 UIVisualEffectView 的模糊半径来创建或多或少的模糊?
- c++ - gtkmm:添加不是类字段的小部件
- nearprotocol - 每次函数调用后更新 block_timestamp
- javascript - 自定义路径上的可拖动元素
- swift - 将观察对象的投影值的属性传递给 @Binding