193 lines
8.3 KiB
C#
193 lines
8.3 KiB
C#
namespace Json2CSharpCodeGenerator.Lib;
|
|
|
|
public interface IJsonClassGeneratorConfig
|
|
{
|
|
/// <summary>
|
|
/// The C# <c>namespace</c> or Java <c>package</c> that the generated types will reside in.<br />
|
|
/// <see langword="null"/> by default. If null/empty/whitespace then no enclosing namespace will be written in the output.
|
|
/// </summary>
|
|
string Namespace { get; set; }
|
|
|
|
/// <summary>
|
|
/// The C# <c>namespace</c> or Java <c>package</c> that "secondary" generated types will reside in.<br />
|
|
/// <see langword="null"/> by default.
|
|
/// </summary>
|
|
string SecondaryNamespace { get; set; }
|
|
|
|
OutputTypes OutputType { get; set; }
|
|
OutputCollectionType CollectionType { get; set; }
|
|
|
|
/// <summary>Options contained within are only respected when <see cref="OutputType"/> == <see cref="OutputTypes.MutableClass"/>.</summary>
|
|
MutableClassConfig MutableClasses { get; }
|
|
|
|
JsonLibrary AttributeLibrary { get; set; }
|
|
JsonPropertyAttributeUsage AttributeUsage { get; set; }
|
|
|
|
bool InternalVisibility { get; set; }
|
|
bool NoHelperClass { get; set; }
|
|
|
|
/// <summary>
|
|
/// When true, then the generated C# and VB.NET classes will have PascalCase property names, which means that <c>[JsonProperty]</c> or <c>[JsonPropertyName]</c> will be applied to all properties if the source JSON uses camelCase names, regardless of <see cref="AttributeUsage"/>.<br />
|
|
/// When false, then the generated C# and VB.NET classes' property names will use the same names as the source JSON (except when a JSON property name cannot be represented by a C# identifier).
|
|
/// </summary>
|
|
bool UsePascalCase { get; set; }
|
|
|
|
bool UseNestedClasses { get; set; }
|
|
|
|
/// <summary>Name of the outer class. Only used when <c><see cref="UseNestedClasses"/> == <see langword="true"/></c>.</summary>
|
|
string MainClass { get; set; }
|
|
|
|
/// <summary>When <see langword="true"/>, then <see cref="System.Reflection.ObfuscationAttribute"/> will be applied to generated types.</summary>
|
|
bool ApplyObfuscationAttributes { get; set; }
|
|
|
|
// bool SingleFile { get; set; }
|
|
bool UseThisKeyWord { get; set; }
|
|
ICodeBuilder CodeWriter { get; set; }
|
|
bool AlwaysUseNullableValues { get; set; }
|
|
bool ExamplesInDocumentation { get; set; }
|
|
bool RemoveToJson { get; set; }
|
|
bool RemoveFromJson { get; set; }
|
|
bool RemoveConstructors { get; set; }
|
|
}
|
|
|
|
public enum OutputTypes
|
|
{
|
|
/// <summary>
|
|
/// C#: Mutable <c>class</c> types.<br />
|
|
/// VB.NET: Mutable <c>Class</c> types.<br />
|
|
/// Java: Mutable Bean <c>class</c>
|
|
/// </summary>
|
|
MutableClass,
|
|
|
|
/// <summary>
|
|
/// C#: Immutable <c>class</c> types. Using <c>[JsonConstructor]</c>.<br />
|
|
/// VB.NET: Immutable <c>Class</c> types. Using <c>[JsonConstructor]</c>.<br />
|
|
/// Java: Not yet implemented. TODO.
|
|
/// </summary>
|
|
ImmutableClass,
|
|
|
|
/// <summary>
|
|
/// C#: Immutable <c>record</c> types.<br />
|
|
/// VB.NET: Not supported.<br />
|
|
/// Java: Not supported.<br />
|
|
/// </summary>
|
|
ImmutableRecord
|
|
}
|
|
|
|
public enum OutputCollectionType
|
|
{
|
|
/// <summary>Expose collections as <c>T[]</c>.</summary>
|
|
Array,
|
|
|
|
/// <summary>
|
|
/// C#/VB.NET: Expose collections as <c><see cref="List{T}"/></c>.<br />
|
|
/// Java: Uses <c>ArrayList<T></c>
|
|
/// </summary>
|
|
MutableList,
|
|
|
|
/// <summary>
|
|
/// C#/VB.NET: Expose collections as <c><see cref="IReadOnlyList{T}"/></c>.<br />
|
|
/// Java: Not supported.
|
|
/// </summary>
|
|
IReadOnlyList,
|
|
|
|
/// <summary>
|
|
/// C#/VB.NET: Expose collections as <c>System.Collections.Immutable.ImmutableArray<T></c>.<br />
|
|
/// Java: Not supported.
|
|
/// </summary>
|
|
/// <remarks><c>ImmutableArray</c> is preferred over <c>ImmutableList</c> when append functionality isn't required.</remarks>
|
|
ImmutableArray
|
|
}
|
|
|
|
public enum OutputMembers
|
|
{
|
|
/// <summary>C# and VB.NET: Uses auto-properties. Java: uses getter/setter methods.</summary>
|
|
AsProperties,
|
|
AsPublicFields,
|
|
// AsPublicPropertiesOverPrivateFields // TODO
|
|
}
|
|
|
|
public enum JsonLibrary
|
|
{
|
|
/// <summary>Use the <see cref="Newtonsoft.Json.JsonPropertyAttribute"/> on generated C# class properties.</summary>
|
|
NewtonsoftJson,
|
|
|
|
/// <summary>Use the <c>[JsonPropertyName]</c> attribute on generated C# class properties.</summary>
|
|
SystemTextJson
|
|
}
|
|
|
|
public enum JsonPropertyAttributeUsage
|
|
{
|
|
/// <summary>The <c>[JsonProperty]</c> or <c>[JsonPropertyName]</c> attributes will be applied to all properties.</summary>
|
|
Always,
|
|
|
|
/// <summary>The <c>[JsonProperty]</c> or <c>[JsonPropertyName]</c> attributes will only be applied to properties with names that cannot be expressed as C# identifiers.</summary>
|
|
OnlyWhenNecessary
|
|
}
|
|
|
|
public class MutableClassConfig
|
|
{
|
|
/// <summary>
|
|
/// When <see langword="true"/>, then all properties for collections are read-only, though the actual collection-type can still be mutable. e.g. <c>public List<String> StringValues { get; }</c><br />
|
|
/// When <see langword="false"/>, then all properties for collections are read-only, though the actual collection-type can still be mutable. e.g. <c>public List<String> StringValues { get; set; }</c><br />
|
|
/// Default is <see langword="false"/>.
|
|
/// </summary>
|
|
public bool ReadOnlyCollectionProperties { get; set; }
|
|
|
|
public OutputMembers Members { get; set; } = OutputMembers.AsProperties;
|
|
}
|
|
|
|
public static class JsonClassGeneratorConfigExtensions
|
|
{
|
|
/// <summary>
|
|
/// Never returns <see langword="null"/>. Returns either:
|
|
/// <list type="bullet">
|
|
/// <item>"<c>[JsonPropertyName("<paramref name="field"/>.<see cref="FieldInfo.JsonMemberName"/>")]</c>" (for <c>System.Text.Json</c>).</item>
|
|
/// <item>"<c>[JsonProperty("<paramref name="field"/>.<see cref="FieldInfo.JsonMemberName"/>")]</c>" (for <c>Newtonsoft.Json</c>).</item>
|
|
/// <item>"<c>[property: JsonPropertyName("<paramref name="field"/>.<see cref="FieldInfo.JsonMemberName"/>")]</c>" (for <c>System.Text.Json</c>) when <see cref="IJsonClassGeneratorConfig.RecordTypes"/> is <see langword="true"/>.</item>
|
|
/// <item>"<c>[property: JsonProperty("<paramref name="field"/>.<see cref="FieldInfo.JsonMemberName"/>")]</c>" (for <c>Newtonsoft.Json</c>) when <see cref="IJsonClassGeneratorConfig.RecordTypes"/> is <see langword="true"/>.</item>
|
|
/// <item>An empty string depending on <paramref name="config"/> and <see cref="FieldInfo.ContainsSpecialChars"/>.</item>
|
|
/// </list>
|
|
/// </summary>
|
|
/// <param name="config">Required. Cannot be <see langword="null"/>.</param>
|
|
/// <param name="field">Required. Cannot be <see langword="null"/>.</param>
|
|
/// <returns></returns>
|
|
public static string GetCSharpJsonAttributeCode(this IJsonClassGeneratorConfig config, FieldInfo field)
|
|
{
|
|
if (config is null)
|
|
throw new ArgumentNullException(nameof(config));
|
|
if (field is null)
|
|
throw new ArgumentNullException(nameof(field));
|
|
|
|
//
|
|
|
|
if (UsePropertyAttribute(config, field))
|
|
{
|
|
bool usingRecordTypes = config.OutputType == OutputTypes.ImmutableRecord;
|
|
string attributeTarget = usingRecordTypes ? "property: " : string.Empty;
|
|
|
|
return config.AttributeLibrary switch
|
|
{
|
|
JsonLibrary.NewtonsoftJson => $"[{attributeTarget}JsonProperty(\"{field.JsonMemberName}\")]",
|
|
JsonLibrary.SystemTextJson => $"[{attributeTarget}JsonPropertyName(\"{field.JsonMemberName}\")]",
|
|
_ => throw new InvalidOperationException("Unrecognized " + nameof(config.AttributeLibrary) + " value: " + config.AttributeLibrary),
|
|
};
|
|
}
|
|
else
|
|
{
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
private static bool UsePropertyAttribute(IJsonClassGeneratorConfig config, FieldInfo field)
|
|
{
|
|
return config.AttributeUsage switch
|
|
{
|
|
JsonPropertyAttributeUsage.Always => true,
|
|
JsonPropertyAttributeUsage.OnlyWhenNecessary => field.ContainsSpecialChars,
|
|
_ => throw new InvalidOperationException("Unrecognized " + nameof(config.AttributeUsage) + " value: " + config.AttributeUsage),
|
|
};
|
|
}
|
|
|
|
public static bool HasNamespace(this IJsonClassGeneratorConfig config) => !string.IsNullOrEmpty(config.Namespace);
|
|
} |