JSON.NET serialize JObject while ignoring null properties

后端 未结 4 1877
说谎
说谎 2020-12-01 16:37

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

4条回答
  •  無奈伤痛
    2020-12-01 16:56

    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())
                {
                    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);
        }
    }
    

    Demo:

    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));
    

    Output:

    {
      "Foo": {
        "P2": "hello world",
        "P4": {
          "P1": 1
        },
        "FooArray": [
          {}
        ]
      }
    }
    

    Fiddle: https://dotnetfiddle.net/wzEOie

    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
        }
      }
    }
    

    Fiddle: https://dotnetfiddle.net/ZdYogJ

提交回复
热议问题