Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix supporting System.Text.Json in CSharpJsonSerializerGenerator #1331

Merged
Show file tree
Hide file tree
Changes from 1 commit
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,85 @@
using System;
using Xunit;

namespace NJsonSchema.CodeGeneration.CSharp.Tests
{
public class CSharpJsonSerializerGeneratorTests
{
[Fact]
public void When_using_SytemTextJson_with_JsonConverters_GenerateJsonSerializerParameterCode_generates_correctly()
{
//// Arrange
var additionalJsonConverters = new string[] { "AdditionalConverter1", "AdditionalConverter2" };
var settings = new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
JsonConverters = new string[] { "CustomConverter1", "CustomConverter2" }
};

//// Act
var output = CSharpJsonSerializerGenerator.GenerateJsonSerializerParameterCode(settings, additionalJsonConverters);
Console.WriteLine(output);

//// Assert
Assert.Equal(", System.Text.Json.JsonSerializerOptions { }; var converters = new System.Text.Json.Serialization.JsonConverter[] { new CustomConverter1(), new CustomConverter2(), new AdditionalConverter1(), new AdditionalConverter2() }", output);
}

[Fact]
public void When_using_NewtonsoftJson_with_JsonConverters_GenerateJsonSerializerParameterCode_generates_correctly()
{
//// Arrange
var additionalJsonConverters = new string[] { "AdditionalConverter1", "AdditionalConverter2" };
var settings = new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.NewtonsoftJson,
JsonConverters = new string[] { "CustomConverter1", "CustomConverter2" }
};

//// Act
var output = CSharpJsonSerializerGenerator.GenerateJsonSerializerParameterCode(settings, additionalJsonConverters);
Console.WriteLine(output);

//// Assert
Assert.Equal(", new Newtonsoft.Json.JsonConverter[] { new CustomConverter1(), new CustomConverter2(), new AdditionalConverter1(), new AdditionalConverter2() }", output);
}

[Fact]
public void When_using_SytemTextJson_with_JsonSerializerOptionsTransformationMethod_GenerateJsonSerializerParameterCode_generates_correctly()
{
//// Arrange
var settings = new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.SystemTextJson,
JsonSerializerOptionsTransformationMethod = "TestJsonSerializerOptionsTransformationMethod"
};

//// Act
var output = CSharpJsonSerializerGenerator.GenerateJsonSerializerParameterCode(settings, null);
Console.WriteLine(output);

//// Assert
Assert.Equal(", TestJsonSerializerOptionsTransformationMethod(System.Text.Json.JsonSerializerOptions { })", output);
}

[Fact]
public void When_using_NewtonsoftJson_with_HandleReferences_and_JsonConverters_and_JsonSerializerSettingsTransformationMethod_GenerateJsonSerializerParameterCode_generates_correctly()
{
//// Arrange
var additionalJsonConverters = new string[] { "AdditionalConverter1", "AdditionalConverter2" };
var settings = new CSharpGeneratorSettings
{
JsonLibrary = CSharpJsonLibrary.NewtonsoftJson,
HandleReferences = true,
JsonConverters = new string[] { "CustomConverter1", "CustomConverter2" },
JsonSerializerSettingsTransformationMethod = "TestJsonSerializerSettingsTransformationMethod",
};

//// Act
var output = CSharpJsonSerializerGenerator.GenerateJsonSerializerParameterCode(settings, additionalJsonConverters);
Console.WriteLine(output);

//// Assert
Assert.Equal(", TestJsonSerializerSettingsTransformationMethod(new Newtonsoft.Json.JsonSerializerSettings { PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All, Converters = new Newtonsoft.Json.JsonConverter[] { new CustomConverter1(), new CustomConverter2(), new AdditionalConverter1(), new AdditionalConverter2() } })", output);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public CSharpGeneratorSettings()
/// <summary>Gets or sets the .NET namespace of the generated types (default: MyNamespace).</summary>
public string Namespace { get; set; }

/// <summary>Gets or sets a value indicating whether a required property must be defined in JSON
/// <summary>Gets or sets a value indicating whether a required property must be defined in JSON
/// (sets Required.Always when the property is required) (default: true).</summary>
public bool RequiredPropertiesMustBeDefined { get; set; }

Expand Down Expand Up @@ -121,9 +121,12 @@ public CSharpGeneratorSettings()
/// <summary>Gets or sets a value indicating whether to use preserve references handling (All) in the JSON serializer (default: false).</summary>
public bool HandleReferences { get; set; }

/// <summary>Gets or sets the name of a static method which is called to transform the JsonSerializerSettings used in the generated ToJson()/FromJson() methods (default: null).</summary>
/// <summary>Gets or sets the name of a static method which is called to transform the JsonSerializerSettings (Newtonsoft.Json) used in the generated ToJson()/FromJson() methods (default: null).</summary>
public string JsonSerializerSettingsTransformationMethod { get; set; }
unchase marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>Gets or sets the name of a static method which is called to transform the JsonSerializerOptions (System.Text.Json) used in the generated ToJson()/FromJson() methods (default: null).</summary>
public string JsonSerializerOptionsTransformationMethod { get; set; }

/// <summary>Gets or sets a value indicating whether to render ToJson() and FromJson() methods (default: true).</summary>
public bool GenerateJsonMethods { get; set; }

Expand Down
103 changes: 73 additions & 30 deletions src/NJsonSchema.CodeGeneration.CSharp/CSharpJsonSerializerGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,90 @@ public static string GenerateJsonSerializerParameterCode(CSharpGeneratorSettings
var jsonConverters = (settings.JsonConverters ?? new string[0]).Concat(additionalJsonConverters ?? new string[0]).ToList();
var hasJsonConverters = jsonConverters.Any();

var useSettingsTransformationMethod = !string.IsNullOrEmpty(settings.JsonSerializerSettingsTransformationMethod);
return settings.JsonLibrary == CSharpJsonLibrary.SystemTextJson ?
string.Empty : // TODO(system.text.json): What to do here?
GenerateForNewtonsoftJson(settings, jsonConverters, hasJsonConverters, useSettingsTransformationMethod);
return GenerateForJsonLibrary(settings, jsonConverters, hasJsonConverters);
}

private static string GenerateForNewtonsoftJson(CSharpGeneratorSettings settings, List<string> jsonConverters, bool hasJsonConverters, bool useSettingsTransformationMethod)
private static string GenerateForJsonLibrary(CSharpGeneratorSettings settings, List<string> jsonConverters, bool hasJsonConverters)
{
if (settings.HandleReferences || useSettingsTransformationMethod)
switch (settings.JsonLibrary)
{
// TODO(system.text.json): Also support System.Text.Json
return ", " +
(useSettingsTransformationMethod ? settings.JsonSerializerSettingsTransformationMethod + "(" : string.Empty) +
"new Newtonsoft.Json.JsonSerializerSettings { " +
(settings.HandleReferences
? "PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All"
: string.Empty) +
(hasJsonConverters
? (settings.HandleReferences ? ", " : string.Empty) + "Converters = " + GenerateConverters(jsonConverters)
: string.Empty) +
" }" +
(useSettingsTransformationMethod ? ")" : string.Empty);
}
else
{
if (hasJsonConverters)
{
return ", " + GenerateConverters(jsonConverters);
}
else
{
case CSharpJsonLibrary.NewtonsoftJson:
var useSettingsTransformationMethod = !string.IsNullOrEmpty(settings.JsonSerializerSettingsTransformationMethod);
if (settings.HandleReferences || useSettingsTransformationMethod)
{
return ", " +
(useSettingsTransformationMethod ? settings.JsonSerializerSettingsTransformationMethod + "(" : string.Empty) +
"new Newtonsoft.Json.JsonSerializerSettings { " +
(settings.HandleReferences
? "PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All"
: string.Empty) +
(hasJsonConverters
? (settings.HandleReferences ? ", " : string.Empty) + "Converters = " + GenerateConverters(jsonConverters, settings.JsonLibrary)
: string.Empty) +

// TODO(newtonsoft.json): Add supporting more options for Newtonsoft.Json (hided for System.Text.Json)
// or it can be handled in JsonSerializerSettingsTransformationMethod?

" }" +
(useSettingsTransformationMethod ? ")" : string.Empty);
}
else
{
if (hasJsonConverters)
{
return ", " + GenerateConverters(jsonConverters, settings.JsonLibrary);
}
else
{
return string.Empty;
}
}
case CSharpJsonLibrary.SystemTextJson:
var useOptionsTransformationMethod = !string.IsNullOrEmpty(settings.JsonSerializerOptionsTransformationMethod);
// TODO: add more conditions?
if (useOptionsTransformationMethod || hasJsonConverters)
{
return ", " +
(useOptionsTransformationMethod ? settings.JsonSerializerOptionsTransformationMethod + "(" : string.Empty) +
"System.Text.Json.JsonSerializerOptions { " +

// TODO(system.text.json): Add supporting more options for System.Text.Json (hided for Newtonsoft.Json)
unchase marked this conversation as resolved.
Show resolved Hide resolved
// or it can be handled in JsonSerializerOptionsTransformationMethod?
//
// "AllowTrailingCommas" (bool), "DefaultBufferSize" (int), "IgnoreNullValues" (bool),
// "IgnoreReadOnlyProperties" (bool), "MaxDepth" (int), "PropertyNameCaseInsensitive" (bool)
// "WriteIndented" (bool), "ReadCommentHandling" (enum - System.Text.Json.JsonCommentHandling),
// "PropertyNamingPolicy" (abstract class - System.Text.Json.JsonNamingPolicy), "Encoder" (abstract class - System.Text.Encodings.Web.JavaScriptEncoder),
// "DictionaryKeyPolicy" (abstract class - System.Text.Json.JsonNamingPolicy)

" }" +
(useOptionsTransformationMethod ? ")" : string.Empty) +
(hasJsonConverters
? "; var converters = " + GenerateConverters(jsonConverters, settings.JsonLibrary)
: string.Empty);
}
else
{
return string.Empty;
}
default: // TODO: possibly add more json converters
return string.Empty;
}
}
}

private static string GenerateConverters(List<string> jsonConverters)
private static string GenerateConverters(List<string> jsonConverters, CSharpJsonLibrary jsonLibrary)
{
if (jsonConverters.Any())
{
return "new Newtonsoft.Json.JsonConverter[] { " + string.Join(", ", jsonConverters.Select(c => "new " + c + "()")) + " }";
switch (jsonLibrary)
{
case CSharpJsonLibrary.NewtonsoftJson:
return "new Newtonsoft.Json.JsonConverter[] { " + string.Join(", ", jsonConverters.Select(c => "new " + c + "()")) + " }";
case CSharpJsonLibrary.SystemTextJson:
return "new System.Text.Json.Serialization.JsonConverter[] { " + string.Join(", ", jsonConverters.Select(c => "new " + c + "()")) + " }";
default: // TODO: possibly add more json converters
return string.Empty;
}
}
else
{
Expand Down