Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ The recommended commit types used are:
- __docs__ for documentation updates e.g. ReadMe update or code documentation updates
- __build__ for build system changes (gradle updates, external dependency updates)
- __ci__ for CI configuration file changes e.g. updating a pipeline
- __chore__ for miscallaneous non-sdk changesin the repo e.g. removing an unused file
- __chore__ for miscallaneous non-sdk changes in the repo e.g. removing an unused file

Adding an exclamation mark after the commit type (`feat!`) or footer with the prefix __BREAKING CHANGE:__ will cause an increment of the _major_ version.
20 changes: 15 additions & 5 deletions src/serialization/json/JsonParseNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Helpers;
using Microsoft.Kiota.Abstractions.Serialization;
using System.Text.Json.Serialization;


#if NET5_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
Expand Down Expand Up @@ -87,42 +89,50 @@ public JsonParseNode(JsonElement node, KiotaJsonSerializationContext jsonSeriali
/// Get the int value from the json node
/// </summary>
/// <returns>A int value</returns>
public int? GetIntValue() => _jsonNode.ValueKind == JsonValueKind.Number
public int? GetIntValue() => IsParsableNumber(_jsonNode.ValueKind, _jsonSerializerContext.Options.NumberHandling)
? _jsonNode.Deserialize(_jsonSerializerContext.Int32)
: null;


/// <summary>
/// Get the float value from the json node
/// </summary>
/// <returns>A float value</returns>
public float? GetFloatValue() => _jsonNode.ValueKind == JsonValueKind.Number
public float? GetFloatValue() => IsParsableNumber(_jsonNode.ValueKind, _jsonSerializerContext.Options.NumberHandling)
? _jsonNode.Deserialize(_jsonSerializerContext.Single)
: null;

/// <summary>
/// Get the Long value from the json node
/// </summary>
/// <returns>A Long value</returns>
public long? GetLongValue() => _jsonNode.ValueKind == JsonValueKind.Number
public long? GetLongValue() => IsParsableNumber(_jsonNode.ValueKind, _jsonSerializerContext.Options.NumberHandling)
? _jsonNode.Deserialize(_jsonSerializerContext.Int64)
: null;

/// <summary>
/// Get the double value from the json node
/// </summary>
/// <returns>A double value</returns>
public double? GetDoubleValue() => _jsonNode.ValueKind == JsonValueKind.Number
public double? GetDoubleValue() => IsParsableNumber(_jsonNode.ValueKind, _jsonSerializerContext.Options.NumberHandling)
? _jsonNode.Deserialize(_jsonSerializerContext.Double)
: null;

/// <summary>
/// Get the decimal value from the json node
/// </summary>
/// <returns>A decimal value</returns>
public decimal? GetDecimalValue() => _jsonNode.ValueKind == JsonValueKind.Number
public decimal? GetDecimalValue() => IsParsableNumber(_jsonNode.ValueKind, _jsonSerializerContext.Options.NumberHandling)
? _jsonNode.Deserialize(_jsonSerializerContext.Decimal)
: null;

private static bool IsParsableNumber(JsonValueKind valueKind, JsonNumberHandling numberHandling) => valueKind switch
{
JsonValueKind.Number => true,
JsonValueKind.String when numberHandling.HasFlag(JsonNumberHandling.AllowReadingFromString) => true,
_ => false
};

/// <summary>
/// Get the guid value from the json node
/// </summary>
Expand Down
238 changes: 238 additions & 0 deletions tests/serialization/json/JsonParseNodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using Microsoft.Kiota.Abstractions;
using Microsoft.Kiota.Abstractions.Serialization;
Expand Down Expand Up @@ -533,5 +534,242 @@ public void GetDateTimeOffsetValue_ReturnCorrectDateTimeOffset()
Assert.Equal(34, result.Value.Minute);
Assert.Equal(56, result.Value.Second);
}

[Theory]
[InlineData("42", 42)]
[InlineData("\"42\"", null)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetIntValue_CanReadNumber(string input, int? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement);

// Act
var actual = parseNode.GetIntValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

static KiotaJsonSerializationContext readNumbersAsStringsContext = new KiotaJsonSerializationContext(
new JsonSerializerOptions()
{
NumberHandling = JsonNumberHandling.AllowReadingFromString
}
);

[Theory]
[InlineData("42", 42)]
[InlineData("\"42\"", 42)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetIntValue_CanReadNumber_AsString(string input, int? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement, readNumbersAsStringsContext);

// Act
var actual = parseNode.GetIntValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("42", 42L)]
[InlineData("\"42\"", null)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetLongValue_CanReadNumber(string input, long? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement);

// Act
var actual = parseNode.GetLongValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("42", 42L)]
[InlineData("\"42\"", 42L)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetLongValue_CanReadNumber_AsString(string input, long? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement, readNumbersAsStringsContext);

// Act
var actual = parseNode.GetLongValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37F)]
[InlineData("\"13.37\"", null)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetFloatValue_CanReadNumber(string input, float? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement);

// Act
var actual = parseNode.GetFloatValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37F)]
[InlineData("\"13.37\"", 13.37F)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetFloatValue_CanReadNumber_AsString(string input, float? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement, readNumbersAsStringsContext);

// Act
var actual = parseNode.GetFloatValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37D)]
[InlineData("\"13.37\"", null)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetDoubleValue_CanReadNumber(string input, double? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement);

// Act
var actual = parseNode.GetDoubleValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37D)]
[InlineData("\"13.37\"", 13.37D)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetDoubleValue_CanReadNumber_AsString(string input, double? expected)
{
// Arrange
using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement, readNumbersAsStringsContext);

// Act
var actual = parseNode.GetDoubleValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37)]
[InlineData("\"13.37\"", null)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetDecimalValue_CanReadNumber(string input, double? expectedDouble)
{
// Arrange
var expected = expectedDouble.HasValue
? Convert.ToDecimal(expectedDouble)
: default(decimal?)
; //13.37M is not supported as a constant expression in attributes

using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement);

// Act
var actual = parseNode.GetDecimalValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}

[Theory]
[InlineData("13.37", 13.37)]
[InlineData("\"13.37\"", 13.37)]
[InlineData("\"not-a-number\"", null)]
[InlineData("null", null)]
public void GetDecimalValue_CanReadNumber_AsString(string input, double? expectedDouble)
{
// Arrange
var expected = expectedDouble.HasValue
? Convert.ToDecimal(expectedDouble)
: default(decimal?)
; //13.37M is not supported as a constant expression in attributes

using var jsonDocument = JsonDocument.Parse(input);
var parseNode = new JsonParseNode(jsonDocument.RootElement, readNumbersAsStringsContext);

// Act
var actual = parseNode.GetDecimalValue();

// Assert
Assert.Equal(expected.HasValue, actual.HasValue);
if(expected.HasValue && actual.HasValue)
{
Assert.Equal(expected.Value, actual.Value);
}
}
}
}
Loading