我有一个 JObject
用作调用 RESTful Web 服务的 模板.这个 JObject
是通过解析器创建的,因为它被用作模板告诉用户端点模式是什么样的,我必须想办法保留所有属性,这就是我默认的原因将它们的值设置为 null
.例如,这是对象最初的样子:
I have a JObject
which is used as a template for calling RESTful web services. This JObject
gets created via a parser and since it's used as a template telling the user what the endpoint schema looks like, I had to figure out a way to preserve all properties, which is why I'm defaulting their values to null
. As as example, this is what the object originally looks like:
{
"Foo":{
"P1":null,
"P2":null,
"P3":null,
"P4":{
"P1":null,
"P2":null,
"P3":null,
},
"FooArray":[
{
"F1":null,
"F2":null,
"F3":null,
}
]
},
"Bar":null
}
然后用户可以根据需要填写各个字段,例如 Foo.P2
和 Foo.P4.P1
:
The user is then able to fill in individual fields as they need, such as Foo.P2
and Foo.P4.P1
:
{
"Foo":{
"P1":null,
"P2":"hello world",
"P3":null,
"P4":{
"P1":1,
"P2":null,
"P3":null,
},
"FooArray":[
{
"F1":null,
"F2":null,
"F3":null,
}
]
},
"Bar":null
}
意味着他们只关心这两个领域.现在我想将此模板 (JObject
) 序列化回 JSON 字符串,但只希望显示那些已填充的字段.所以我尝试了这个:
meaning they only care about those two fields. Now I want to serialize this template (JObject
) back to a JSON string, but want only those fields that are populated to show up. So I tried this:
string json = JsonConvert.SerializeObject(template,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
很遗憾,这不起作用.我遇到了 这个问题 并意识到对象中的 null
值是实际的 JToken
类型,而不是真正的 null
,这是有道理的.但是,在这种非常特殊的情况下,我需要能够摆脱这些未使用"的字段.我尝试手动迭代节点并删除它们,但这也不起作用.请注意,我使用的唯一托管类型是 JObject
;我没有将对象转换为或定义属性的模型,因为此模板"在运行时被解析.我只是想知道是否有人遇到过这样的问题并有任何见解.非常感谢任何帮助!
Unfortunately, this didn't work. I came across this question and realized that a null
value in the object is an actual JToken
type and not really a null
, which makes sense. However, in this very particular case, I need to be able to get rid of these "unused" fields. I tried manually iterating over nodes and removing them but that didn't work either. Note that the only managed type I'm using is JObject
; I don't have a model to convert the object to or define attributes on, since this "template" gets resolved at runtime. I was just wondering if anyone has encountered a problem like this and has any insights. Any help is greatly appreciated!
您可以使用如下递归辅助方法从 JToken
中删除 null
值序列化之前的层次结构.
You can use a recursive helper method like the one below to remove the null
values from your JToken
hierarchy prior to serializing it.
using System;
using Newtonsoft.Json.Linq;
public static class JsonHelper
{
public static JToken RemoveEmptyChildren(JToken token)
{
if (token.Type == JTokenType.Object)
{
JObject copy = new JObject();
foreach (JProperty prop in token.Children<JProperty>())
{
JToken child = prop.Value;
if (child.HasValues)
{
child = RemoveEmptyChildren(child);
}
if (!IsEmpty(child))
{
copy.Add(prop.Name, child);
}
}
return copy;
}
else if (token.Type == JTokenType.Array)
{
JArray copy = new JArray();
foreach (JToken item in token.Children())
{
JToken child = item;
if (child.HasValues)
{
child = RemoveEmptyChildren(child);
}
if (!IsEmpty(child))
{
copy.Add(child);
}
}
return copy;
}
return token;
}
public static bool IsEmpty(JToken token)
{
return (token.Type == JTokenType.Null);
}
}
演示:
string json = @"
{
""Foo"": {
""P1"": null,
""P2"": ""hello world"",
""P3"": null,
""P4"": {
""P1"": 1,
""P2"": null,
""P3"": null
},
""FooArray"": [
{
""F1"": null,
""F2"": null,
""F3"": null
}
]
},
""Bar"": null
}";
JToken token = JsonHelper.RemoveEmptyChildren(JToken.Parse(json));
Console.WriteLine(token.ToString(Formatting.Indented));
输出:
{
"Foo": {
"P2": "hello world",
"P4": {
"P1": 1
},
"FooArray": [
{}
]
}
}
小提琴:https://dotnetfiddle.net/wzEOie
请注意,在删除所有空值之后,您将在 FooArray
中有一个空对象,这可能是您不想要的.(如果那个对象被移除了,那么你会得到一个空的 FooArray
,你也可能不想要它.)如果你想让帮助方法在移除时更积极,你可以改变IsEmpty 函数到此:
Notice that, after removing all null values, you will have an empty object in the FooArray
, which you may not want. (And if that object were removed, then you'd have an empty FooArray
, which you also may not want.) If you want to make the helper method more aggressive in its removal, you can change the IsEmpty function to this:
public static bool IsEmpty(JToken token)
{
return (token.Type == JTokenType.Null) ||
(token.Type == JTokenType.Array && !token.HasValues) ||
(token.Type == JTokenType.Object && !token.HasValues);
}
进行该更改后,您的输出将如下所示:
With that change in place, your output would look like this instead:
{
"Foo": {
"P2": "hello world",
"P4": {
"P1": 1
}
}
}
小提琴:https://dotnetfiddle.net/ZdYogJ
这篇关于JSON.NET 序列化 JObject 而忽略空属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!