我正在.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。
答案 0 :(得分:1)
标题可能有点误导,但是OP基本上需要的是一种在不占用过多内存的情况下解析现有(大型)JRaw
对象的方法。
我进行了一些测试,并且能够使用JsonTextReader
找到解决方案。
我不知道OP的json字符串的确切结构,所以我假设是这样的:
[
{
"context": {
"id": 10
}
},
{
"context": {
"id": 20
}
},
{
"context": {
"id": 30
}
}
]
结果将是具有id值(10、20、30)的整数数组。
因此,该方法采用JRaw
对象作为参数,并使用JsonTextReader
提取ID。
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的诊断工具拍摄了以下快照,以检查内存使用情况:
JRaw rawJson = CreateRawJson();
列表ID = GetIds(rawJson).ToList();