Skip to content

Commit c054c9d

Browse files
authored
Merge pull request #3141 from microsoftgraph/fix/null-valued-implementation
Updates implementation of allowing null valued properties to handle array and object schema types differently
2 parents feca6ec + 516a568 commit c054c9d

File tree

4 files changed

+85
-33
lines changed

4 files changed

+85
-33
lines changed

src/readme.graph.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
azure: false
77
powershell: true
88
version: latest
9-
#use: "@autorest/powershell@3.0.509"
109
use: "$(this-folder)../autorest.powershell"
1110
export-properties-for-dict: false
1211
metadata:
@@ -651,7 +650,15 @@ directive:
651650
// Fix double = in date parameter. Temp fix for https://github.com/Azure/autorest.powershell/issues/1025.
652651
let dateAssignmentRegex = /(date="\n.*)(\+.*"=")(.*\+.*date)/gmi
653652
$ = $.replace(dateAssignmentRegex, '$1 $3');
654-
return $;
653+
654+
// Allow sending of serialized null properties located in cleanedBody
655+
$ = $.replace(/request\.Content\s*=\s*new\s+global::System\.Net\.Http\.StringContent\(\s*null\s*!=\s*body\s*\?\s*body\.ToJson\(null\)\.ToString\(\)\s*:\s*@"{}",\s*global::System\.Text\.Encoding\.UTF8\);/g,'request.Content = new global::System.Net.Http.StringContent(cleanedBody, global::System.Text.Encoding.UTF8);');
656+
657+
$ = $.replace(/request\.Content\s*=\s*new\s+global::System\.Net\.Http\.StringContent\(\s*null\s*!=\s*body\s*\?\s*new\s+Microsoft\.Graph\.PowerShell\.Runtime\.Json\.XNodeArray\(.*?\)\s*:\s*null,\s*global::System\.Text\.Encoding\.UTF8\);/g,'request.Content = new global::System.Net.Http.StringContent(cleanedBody, global::System.Text.Encoding.UTF8);');
658+
659+
$ = $.replace(/request\.Content\s*=\s*new\s+global::System\.Net\.Http\.StringContent\(\s*null\s*!=\s*body\s*\?\s*new\s+Microsoft\.Graph\.Beta\.PowerShell\.Runtime\.Json\.XNodeArray\(.*?\)\s*:\s*null,\s*global::System\.Text\.Encoding\.UTF8\);/g,'request.Content = new global::System.Net.Http.StringContent(cleanedBody, global::System.Text.Encoding.UTF8);');
660+
661+
return $
655662
}
656663
657664
# Fix enums with underscore.

tools/Custom/JsonExtensions.cs

+51-28
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,85 @@
1-
namespace Microsoft.Graph.PowerShell.JsonUtilities
1+
namespace NamespacePrefixPlaceholder.PowerShell.JsonUtilities
22
{
33
using Newtonsoft.Json.Linq;
4+
using System;
45
using System.Linq;
56

67
public static class JsonExtensions
78
{
89
/// <summary>
9-
/// Removes JSON properties that have a value of "defaultnull" and converts properties with values of "null" to actual JSON null values.
10+
/// Recursively removes properties with the value "defaultnull" from a JSON structure
11+
/// and replaces string values that are "null" with actual null values.
12+
/// This method supports both JObject (JSON objects) and JArray (JSON arrays),
13+
/// ensuring proper cleanup of nested structures.
1014
/// </summary>
11-
/// <param name="jsonObject">The JObject to process and clean.</param>
12-
/// <returns>
13-
/// A JSON string representation of the cleaned JObject with "defaultnull" properties removed and "null" values converted to JSON null.
14-
/// </returns>
15+
/// <param name="token">The JToken (JObject or JArray) to process.</param>
16+
/// <returns>The cleaned JSON string with "defaultnull" values removed and "null" strings converted to null.</returns>
1517
/// <example>
1618
/// JObject json = JObject.Parse(@"{""name"": ""John"", ""email"": ""defaultnull"", ""address"": ""null""}");
1719
/// string cleanedJson = json.RemoveDefaultNullProperties();
1820
/// Console.WriteLine(cleanedJson);
1921
/// // Output: { "name": "John", "address": null }
2022
/// </example>
21-
public static string RemoveDefaultNullProperties(this JObject jsonObject)
23+
public static string RemoveDefaultNullProperties(this JToken token)
2224
{
2325
try
2426
{
25-
foreach (var property in jsonObject.Properties().ToList())
27+
if (token is JObject jsonObject)
2628
{
27-
if (property.Value.Type == JTokenType.Object)
29+
foreach (var property in jsonObject.Properties().ToList())
2830
{
29-
RemoveDefaultNullProperties((JObject)property.Value);
30-
}
31-
else if (property.Value.Type == JTokenType.Array)
32-
{
33-
foreach (var item in property.Value)
31+
if (property.Value.Type == JTokenType.Object)
3432
{
35-
if (item.Type == JTokenType.Object)
36-
{
37-
RemoveDefaultNullProperties((JObject)item);
38-
}
33+
RemoveDefaultNullProperties(property.Value);
34+
}
35+
else if (property.Value.Type == JTokenType.Array)
36+
{
37+
RemoveDefaultNullProperties(property.Value);
38+
}
39+
else if (property.Value.Type == JTokenType.String && property.Value.ToString().Equals("defaultnull",StringComparison.Ordinal))
40+
{
41+
property.Remove();
42+
}
43+
else if (property.Value.Type == JTokenType.String && property.Value.ToString().Equals("null",StringComparison.Ordinal))
44+
{
45+
property.Value = JValue.CreateNull();
3946
}
4047
}
41-
else if (property.Value.Type == JTokenType.String && property.Value.ToString() == "defaultnull")
42-
{
43-
property.Remove();
44-
}
45-
else if (property.Value.Type == JTokenType.String && (property.Value.ToString() == "null"))
48+
}
49+
else if (token is JArray jsonArray)
50+
{
51+
// Process each item in the JArray
52+
for (int i = jsonArray.Count - 1; i >= 0; i--)
4653
{
47-
property.Value = JValue.CreateNull();
54+
var item = jsonArray[i];
55+
56+
if (item.Type == JTokenType.Object)
57+
{
58+
RemoveDefaultNullProperties(item);
59+
}
60+
else if (item.Type == JTokenType.String && item.ToString().Equals("defaultnull",StringComparison.Ordinal))
61+
{
62+
jsonArray.RemoveAt(i); // Remove the "defaultnull" string from the array
63+
}
64+
else if (item.Type == JTokenType.String && item.ToString().Equals("null",StringComparison.Ordinal))
65+
{
66+
jsonArray[i] = JValue.CreateNull(); // Convert "null" string to actual null
67+
}
4868
}
4969
}
5070
}
51-
catch (System.Exception)
71+
catch (System.Exception ex)
5272
{
53-
return jsonObject.ToString(); // Return the original string if parsing fails
73+
Console.WriteLine($"Error cleaning JSON: {ex.Message}");
74+
return token.ToString(); // Return the original JSON if any error occurs
5475
}
55-
return jsonObject.ToString();
76+
77+
return token.ToString();
5678
}
79+
5780
public static string ReplaceAndRemoveSlashes(this string body)
5881
{
5982
return body.Replace("/", "").Replace("\\", "").Replace("rn", "").Replace("\"{", "{").Replace("}\"", "}");
6083
}
6184
}
62-
}
85+
}

tools/Tests/JsonUtilitiesTest/JsonExtensionsTests.cs

+24-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System;
33
using Newtonsoft.Json.Linq;
44
using Xunit;
5-
using Microsoft.Graph.PowerShell.JsonUtilities;
5+
using NamespacePrefixPlaceholder.PowerShell.JsonUtilities;
66

77
public class JsonExtensionsTests
88
{
@@ -45,7 +45,7 @@ public void RemoveDefaultNullProperties_ShouldConvertStringNullToJsonNull()
4545

4646
// Assert
4747
Assert.Null(result["position"]?.Value<string>());
48-
Assert.Equal("",result["team"]?.ToString());
48+
Assert.Equal("", result["team"]?.ToString());
4949
Assert.Equal("Tim", result["displayname"]?.ToString());
5050
Assert.Equal(2000000, result["salary"]?.ToObject<int>());
5151
}
@@ -124,5 +124,27 @@ public void RemoveDefaultNullProperties_ShouldNotAlterValidData()
124124
Assert.Equal("mayabi@example.com", result["email"]?.ToString());
125125
Assert.Equal(2000000, result["salary"]?.ToObject<int>());
126126
}
127+
128+
//Add tests for json arrays
129+
[Fact]
130+
public void RemoveDefaultNullProperties_ShouldRemoveDefaultNullValuesInJsonArray()
131+
{
132+
// Arrange
133+
JArray json = JArray.Parse(@"[
134+
{ ""displayname"": ""Tim"", ""email"": ""defaultnull"" }
135+
136+
]");
137+
138+
// Act
139+
string cleanedJson = json.RemoveDefaultNullProperties();
140+
JArray result = JArray.Parse(cleanedJson);
141+
142+
// Assert
143+
Assert.Equal("Tim", result[0]?["displayname"]?.ToString());
144+
Assert.False(result[0].ToObject<JObject>().ContainsKey("email"));
145+
146+
}
147+
148+
127149
}
128150

0 commit comments

Comments
 (0)