Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Auth0.Core.Serialization
{
internal class StringOrStringArrayJsonConverter : JsonConverter
{
public override bool CanWrite => false;
public override bool CanConvert(Type objectType)
{
return true;
}

public override object ReadJson(
JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartArray)
{
// Deserialize as string array and return;
var array = JArray.Load(reader);
return array.ToObject<string[]>();
}

if (reader.TokenType == JsonToken.String)
{
// Deserialize as a single string
return reader.Value?.ToString();
}

return null;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}
6 changes: 5 additions & 1 deletion src/Auth0.ManagementApi/Models/LogEntry.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;

using Newtonsoft.Json;

using Auth0.Core.Serialization;

namespace Auth0.ManagementApi.Models
{
/// <summary>
Expand Down Expand Up @@ -144,7 +147,8 @@
/// Scope permissions applied to the event
/// </summary>
[JsonProperty("scope")]
public string Scope { get; set; }
[JsonConverter(typeof(StringOrStringArrayJsonConverter))]
public dynamic Scope { get; set; }

Check warning on line 151 in src/Auth0.ManagementApi/Models/LogEntry.cs

View check run for this annotation

Codecov / codecov/patch

src/Auth0.ManagementApi/Models/LogEntry.cs#L151

Added line #L151 was not covered by tests

/// <summary>
/// Unique ID of the event
Expand Down
125 changes: 125 additions & 0 deletions tests/Auth0.Core.UnitTests/StringOrStringArrayConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;
using System.IO;
using Auth0.Core.Serialization;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit;

namespace Auth0.Core.UnitTests;

public class StringOrStringArrayJsonConverterTests
{
internal class StringOrStringArrayJsonConverterData
{
[JsonProperty("value")]
[JsonConverter(typeof(StringOrStringArrayJsonConverter))]
public dynamic Value { get; set; }
}

[Fact]
public void CanConvert_ShouldReturnTrue_ForAnyType()
{
// Act
var converter = new StringOrStringArrayJsonConverter();
var result = converter.CanConvert(typeof(object));

// Assert
Assert.True(result);
}

[Fact]
public void CanWrite_ShouldReturnFalse_Always()
{
// Act
var converter = new StringOrStringArrayJsonConverter();
Assert.False(converter.CanWrite);
}

[Fact]
public void WriteJson_ShouldThrow_ForAnyInputs()
{
// Act
var converter = new StringOrStringArrayJsonConverter();
Assert.Throws<NotImplementedException>( () => converter.WriteJson(null!, null, new JsonSerializer()));
}

[Fact]
public void ReadJson_ShouldDeserializeStringArray_WhenJsonIsArray()
{
// Arrange
var json = "[\"value1\", \"value2\"]";
var reader = new JsonTextReader(new StringReader(json));
reader.Read();
var converter = new StringOrStringArrayJsonConverter();

// Act
var result = converter.ReadJson(reader, typeof(string[]), null, new JsonSerializer());

// Assert
Assert.IsType<string[]>(result);
Assert.Equal(new[] { "value1", "value2" }, result);
}

[Fact]
public void ReadJson_ShouldDeserializeString_WhenJsonIsString()
{
// Arrange
var json = "\"value\"";
var reader = new JsonTextReader(new StringReader(json));
reader.Read();
var converter = new StringOrStringArrayJsonConverter();

// Act
var result = converter.ReadJson(reader, typeof(string), null, new JsonSerializer());

// Assert
Assert.IsType<string>(result);
Assert.Equal("value", result);
}

[Fact]
public void ReadJson_ShouldReturnNull_WhenJsonIsNotStringOrArray()
{
// Arrange
var json = "123";
var reader = new JsonTextReader(new StringReader(json));
reader.Read();
var converter = new StringOrStringArrayJsonConverter();

// Act
var result = converter.ReadJson(reader, typeof(object), null, new JsonSerializer());

// Assert
Assert.Null(result);
}

[Fact]
public void Should_deserialize_string()
{
var content = "{ 'value': 'test' }";

var parsed = JsonConvert.DeserializeObject<StringOrStringArrayJsonConverterData>(content);

Assert.Equal("test", parsed.Value);
}

[Fact]
public void Should_deserialize_object_as_string_array()
{
var content = "{ 'value': [\"value1\", \"value2\"] }";

var parsed = JsonConvert.DeserializeObject<StringOrStringArrayJsonConverterData>(content);

new[] { "value1", "value2" }.Should().BeEquivalentTo(parsed.Value);
}

[Fact]
public void Should_deserialize_when_omitted()
{
var content = "{}";

var parsed = JsonConvert.DeserializeObject<StringOrStringArrayJsonConverterData>(content);

Assert.Null(parsed.Value);
}
}
Loading