是否有更优雅的方法使用 system.text.json 从 JSON 对象获取特定值
Is there a more elegant way to get specific value from JSON object using system.text.json
考虑这个 Json 对象:
{
"main": {
"2058": {
"id": "2058",
"name": "foo",
"attrib1": "17",
"domain": "somewhere.net",
"enabled": "1",
"permissions": [
"admin",
"user",
"guest",
"vpn",
"power"
]
}
},
"validate": {
"2058": {
"id": "2058",
"name": "foo",
"attrib1": "17",
"domain": "somewhere.net",
"enabled": "1",
"permissions": [
"admin",
"user",
"guest",
"vpn",
"power"
]
}
},
"result": "ok"
}
在"enabled"和"permissions"之间,我漏掉了好几百对。 "validate" 部分是 "main" 的精确副本,而 "result" 是结果。
我想从主要部分获取 2 个特定值。 "id" 和 "domain"。我使用以下代码来执行此操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace JsonParse
{
class Program
{
static void Main()
{
string json = "{" +
"\"main\":{" +
"\"2058\":{" +
"\"id\":\"2058\"," +
"\"name\":\"foo\"," +
"\"attrib1\":\"17\"," +
"\"domain\":\"somewhere.net\"," +
"\"enabled\":\"1\"," +
"\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
"}" +
"}," +
"\"validate\":{" +
"\"2058\":{" +
"\"id\":\"2058\"," +
"\"name\":\"foo\"," +
"\"attrib1\":\"17\"," +
"\"domain\":\"somewhere.net\"," +
"\"enabled\":\"1\"," +
"\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
"}" +
"}," +
"\"result\":\"ok\"" +
"}";
foreach (KeyValuePair<string, object> item in JsonSerializer.Deserialize<Dictionary<string, object>>(json))
{
if (item.Key == "main")
{
Dictionary<string, object> pairs = JsonSerializer.Deserialize<Dictionary<string, object>>(item.Value.ToString());
Dictionary<string, object> pairs1 = JsonSerializer.Deserialize<Dictionary<string, object>>(pairs.First().Value.ToString());
foreach (KeyValuePair<string, object> valuePair in pairs1)
{
if (valuePair.Key == "id" || valuePair.Key == "domain")
{
Console.WriteLine("Key: " + valuePair.Key + "\nValue: " + valuePair.Value);
}
}
}
}
}
}
}
由此,我得到了“2058”和 "somewhere.net",但是是否有更优雅的方法来获取值而不是反序列化 3 次?
如果你只需要 main
属性 你可以使用 json path 到 select 所有 "mains" 通过 Newtonsoft Json.NET:
var pairs = JObject.Parse(js).SelectTokens("$.main.*")
.Select(j => (id:j["id"],domain: j["domain"]))
.ToList();
或者只是反序列化为相应的结构(使用 System.Text.Json
或 Newtonsoft):
class MyClass
{
public Dictionary<string, InnerClass> main { get; set; }
}
class InnerClass
{
public string id { get; set; }
public string domain { get; set; }
}
ICollection<InnerClass> mains= JsonSerializer.Deserialize<MyClass>(js).main.Values; // System.Text.Json
如果您使用的是System.Text.Json
API,您可以先将您的JSON解析为JsonDocument
,然后枚举其属性。首先获取 main
对象,然后展平其子属性并通过 id
和 domain
names
找到所需的值
using var document = JsonDocument.Parse(jsonString);
var main = document.RootElement.EnumerateObject().FirstOrDefault(p => p.Name == "main");
var properties = main.Value.EnumerateObject().SelectMany(p => p.Value.EnumerateObject()).ToList();
var id = properties.FirstOrDefault(p => p.Name == "id").Value.GetString();
var domain = properties.FirstOrDefault(p => p.Name == "domain").Value.GetString();
考虑这个 Json 对象:
{
"main": {
"2058": {
"id": "2058",
"name": "foo",
"attrib1": "17",
"domain": "somewhere.net",
"enabled": "1",
"permissions": [
"admin",
"user",
"guest",
"vpn",
"power"
]
}
},
"validate": {
"2058": {
"id": "2058",
"name": "foo",
"attrib1": "17",
"domain": "somewhere.net",
"enabled": "1",
"permissions": [
"admin",
"user",
"guest",
"vpn",
"power"
]
}
},
"result": "ok"
}
在"enabled"和"permissions"之间,我漏掉了好几百对。 "validate" 部分是 "main" 的精确副本,而 "result" 是结果。
我想从主要部分获取 2 个特定值。 "id" 和 "domain"。我使用以下代码来执行此操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
namespace JsonParse
{
class Program
{
static void Main()
{
string json = "{" +
"\"main\":{" +
"\"2058\":{" +
"\"id\":\"2058\"," +
"\"name\":\"foo\"," +
"\"attrib1\":\"17\"," +
"\"domain\":\"somewhere.net\"," +
"\"enabled\":\"1\"," +
"\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
"}" +
"}," +
"\"validate\":{" +
"\"2058\":{" +
"\"id\":\"2058\"," +
"\"name\":\"foo\"," +
"\"attrib1\":\"17\"," +
"\"domain\":\"somewhere.net\"," +
"\"enabled\":\"1\"," +
"\"permissions\":[\"admin\",\"user\",\"guest\",\"vpn\",\"power\"]" +
"}" +
"}," +
"\"result\":\"ok\"" +
"}";
foreach (KeyValuePair<string, object> item in JsonSerializer.Deserialize<Dictionary<string, object>>(json))
{
if (item.Key == "main")
{
Dictionary<string, object> pairs = JsonSerializer.Deserialize<Dictionary<string, object>>(item.Value.ToString());
Dictionary<string, object> pairs1 = JsonSerializer.Deserialize<Dictionary<string, object>>(pairs.First().Value.ToString());
foreach (KeyValuePair<string, object> valuePair in pairs1)
{
if (valuePair.Key == "id" || valuePair.Key == "domain")
{
Console.WriteLine("Key: " + valuePair.Key + "\nValue: " + valuePair.Value);
}
}
}
}
}
}
}
由此,我得到了“2058”和 "somewhere.net",但是是否有更优雅的方法来获取值而不是反序列化 3 次?
如果你只需要 main
属性 你可以使用 json path 到 select 所有 "mains" 通过 Newtonsoft Json.NET:
var pairs = JObject.Parse(js).SelectTokens("$.main.*")
.Select(j => (id:j["id"],domain: j["domain"]))
.ToList();
或者只是反序列化为相应的结构(使用 System.Text.Json
或 Newtonsoft):
class MyClass
{
public Dictionary<string, InnerClass> main { get; set; }
}
class InnerClass
{
public string id { get; set; }
public string domain { get; set; }
}
ICollection<InnerClass> mains= JsonSerializer.Deserialize<MyClass>(js).main.Values; // System.Text.Json
如果您使用的是System.Text.Json
API,您可以先将您的JSON解析为JsonDocument
,然后枚举其属性。首先获取 main
对象,然后展平其子属性并通过 id
和 domain
names
using var document = JsonDocument.Parse(jsonString);
var main = document.RootElement.EnumerateObject().FirstOrDefault(p => p.Name == "main");
var properties = main.Value.EnumerateObject().SelectMany(p => p.Value.EnumerateObject()).ToList();
var id = properties.FirstOrDefault(p => p.Name == "id").Value.GetString();
var domain = properties.FirstOrDefault(p => p.Name == "domain").Value.GetString();