238 lines
8.3 KiB
C#
238 lines
8.3 KiB
C#
using System.Text;
|
|
|
|
namespace Json2CSharpCodeGenerator.Lib.CodeWriters;
|
|
|
|
public class JavaCodeWriter : ICodeBuilder
|
|
{
|
|
public string FileExtension => ".java";
|
|
|
|
public string DisplayName => "Java";
|
|
|
|
private static readonly HashSet<string> _ReservedKeywords = new(comparer: StringComparer.Ordinal)
|
|
{
|
|
// https://en.wikipedia.org/wiki/List_of_Java_keywords
|
|
// `Array.from( document.querySelectorAll('dl > dt > code') ).map( e => '"' + e.textContent + '"' ).sort().join( ", " )`
|
|
|
|
"abstract",
|
|
"assert",
|
|
"boolean",
|
|
"break",
|
|
"byte",
|
|
"case",
|
|
"catch",
|
|
"char",
|
|
"class",
|
|
"const",
|
|
"const",
|
|
"continue",
|
|
"default",
|
|
"do",
|
|
"double",
|
|
"else",
|
|
"enum",
|
|
"extends",
|
|
"false",
|
|
"final",
|
|
"finally",
|
|
"float",
|
|
"for",
|
|
"goto",
|
|
"goto",
|
|
"if",
|
|
"implements",
|
|
"import",
|
|
"instanceof",
|
|
"int",
|
|
"interface",
|
|
"long",
|
|
"native",
|
|
"new",
|
|
"non-sealed",
|
|
"null",
|
|
"open",
|
|
"opens",
|
|
"package",
|
|
"permits",
|
|
"private",
|
|
"protected",
|
|
"provides",
|
|
"public",
|
|
"record",
|
|
"return",
|
|
"sealed",
|
|
"short",
|
|
"static",
|
|
"strictfp",
|
|
"super",
|
|
"switch",
|
|
"synchronized",
|
|
"this",
|
|
"throw",
|
|
"throws",
|
|
"to",
|
|
"transient",
|
|
"transitive",
|
|
"true",
|
|
"try",
|
|
"uses",
|
|
"var",
|
|
"void",
|
|
"volatile",
|
|
"while",
|
|
"with",
|
|
"yield"
|
|
};
|
|
|
|
IReadOnlyCollection<string> ICodeBuilder.ReservedKeywords => _ReservedKeywords;
|
|
public bool IsReservedKeyword(string word) => _ReservedKeywords.Contains(word ?? string.Empty);
|
|
|
|
public string GetTypeName(JsonType type, IJsonClassGeneratorConfig config)
|
|
{
|
|
return type.Type switch
|
|
{
|
|
JsonTypeEnum.Anything => "Object",
|
|
JsonTypeEnum.Array => GetCollectionTypeName(elementTypeName: GetTypeName(type.InternalType, config), config.CollectionType),
|
|
JsonTypeEnum.Dictionary => "HashMap<String, " + GetTypeName(type.InternalType, config) + ">",
|
|
JsonTypeEnum.Boolean => "boolean",
|
|
JsonTypeEnum.Float => "double",
|
|
JsonTypeEnum.Integer => "int",
|
|
JsonTypeEnum.NonConstrained => "Object",
|
|
JsonTypeEnum.NullableBoolean => "boolean",
|
|
JsonTypeEnum.NullableFloat => "double",
|
|
JsonTypeEnum.NullableInteger => "int",
|
|
JsonTypeEnum.NullableLong => "long",
|
|
JsonTypeEnum.NullableDate => "Date",
|
|
JsonTypeEnum.Long => "long",
|
|
JsonTypeEnum.Date => "Date",
|
|
JsonTypeEnum.NullableSomething => "Object",
|
|
JsonTypeEnum.Object => type.NewAssignedName,
|
|
JsonTypeEnum.String => "String",
|
|
_ => throw new NotSupportedException("Unsupported json type"),
|
|
};
|
|
}
|
|
|
|
private static string GetCollectionTypeName(string elementTypeName, OutputCollectionType type)
|
|
{
|
|
return type switch
|
|
{
|
|
OutputCollectionType.Array => elementTypeName + "[]",
|
|
OutputCollectionType.MutableList => "ArrayList<" + elementTypeName + ">",
|
|
OutputCollectionType.IReadOnlyList or OutputCollectionType.ImmutableArray => throw new NotSupportedException("Java does not have in-box interfaces for read-only and immutable collections."),
|
|
_ => throw new ArgumentOutOfRangeException(paramName: nameof(type), actualValue: type, message: "Invalid " + nameof(OutputCollectionType) + " enum value."),
|
|
};
|
|
}
|
|
|
|
public void WriteClass(IJsonClassGeneratorConfig config, StringBuilder sw, JsonType type)
|
|
{
|
|
string visibility = config.InternalVisibility ? "" : "public";
|
|
|
|
_ = sw.AppendFormat("{0} class {1}", visibility, type.AssignedName);
|
|
_ = sw.AppendLine("{");
|
|
|
|
string prefix = config.UseNestedClasses && !type.IsRoot ? "" : " ";
|
|
|
|
WriteClassMembers(config, sw, type, prefix);
|
|
|
|
if (config.UseNestedClasses && !type.IsRoot)
|
|
_ = sw.AppendLine(" }");
|
|
|
|
if (!config.UseNestedClasses)
|
|
_ = sw.AppendLine("}");
|
|
|
|
_ = sw.AppendLine();
|
|
}
|
|
|
|
public void WriteClassMembers(IJsonClassGeneratorConfig config, StringBuilder sw, JsonType type, string prefix)
|
|
{
|
|
foreach (FieldInfo field in type.Fields)
|
|
{
|
|
if (config.UsePascalCase || config.ExamplesInDocumentation)
|
|
_ = sw.AppendLine();
|
|
|
|
// Check if property name starts with number
|
|
string memberName = field.MemberName;
|
|
if (!string.IsNullOrEmpty(field.MemberName) && char.IsDigit(field.MemberName[0]))
|
|
memberName = "_" + memberName;
|
|
|
|
if (IsReservedKeyword(memberName))
|
|
memberName = "my" + memberName;
|
|
|
|
if (config.MutableClasses.Members == OutputMembers.AsProperties)
|
|
{
|
|
_ = sw.AppendFormat(prefix + "@JsonProperty" + "(\"{0}\") {1}", field.JsonMemberName, Environment.NewLine);
|
|
_ = sw.AppendFormat(prefix + "public {0} get{1}() {{ \r\t\t return this.{2}; }} {3}", field.Type.GetTypeName(), ChangeFirstChar(memberName), ChangeFirstChar(memberName, false), Environment.NewLine);
|
|
_ = sw.AppendFormat(prefix + "public void set{1}({0} {2}) {{ \r\t\t this.{2} = {2}; }} {3}", field.Type.GetTypeName(), ChangeFirstChar(memberName), ChangeFirstChar(memberName, false), Environment.NewLine);
|
|
_ = sw.AppendFormat(prefix + "{0} {1};", field.Type.GetTypeName(), ChangeFirstChar(memberName, false));
|
|
_ = sw.AppendLine();
|
|
}
|
|
else if (config.MutableClasses.Members == OutputMembers.AsPublicFields)
|
|
{
|
|
memberName = ChangeFirstChar(memberName, false);
|
|
if (field.JsonMemberName != memberName)
|
|
{
|
|
_ = sw.AppendFormat(prefix + "@JsonProperty" + "(\"{0}\") {1}", field.JsonMemberName, Environment.NewLine);
|
|
}
|
|
_ = sw.AppendFormat(prefix + "public {0} {1};{2}", field.Type.GetTypeName(), memberName, Environment.NewLine);
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Unsupported " + nameof(OutputMembers) + " value: " + config.MutableClasses.Members);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string ChangeFirstChar(string value, bool toCaptial = true)
|
|
{
|
|
if (value == null)
|
|
throw new ArgumentNullException("value");
|
|
if (value.Length == 0)
|
|
return value;
|
|
StringBuilder sb = new();
|
|
|
|
_ = sb.Append(toCaptial ? char.ToUpper(value[0]) : char.ToLower(value[0]));
|
|
_ = sb.Append(value.Substring(1));
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public void WriteFileStart(IJsonClassGeneratorConfig config, StringBuilder sw)
|
|
{
|
|
// foreach (var line in JsonClassGenerator.FileHeader)
|
|
// {
|
|
// sw.WriteLine("// " + line);
|
|
// }
|
|
}
|
|
|
|
public void WriteFileEnd(IJsonClassGeneratorConfig config, StringBuilder sw)
|
|
{
|
|
if (config.UseNestedClasses)
|
|
{
|
|
_ = sw.AppendLine(" }");
|
|
}
|
|
}
|
|
|
|
public void WriteNamespaceStart(IJsonClassGeneratorConfig config, StringBuilder sw, bool root)
|
|
{
|
|
_ = sw.AppendLine();
|
|
_ = sw.AppendFormat("package {0};", root && !config.UseNestedClasses ? config.Namespace : (config.SecondaryNamespace ?? config.Namespace));
|
|
_ = sw.AppendLine();
|
|
}
|
|
|
|
public void WriteNamespaceEnd(IJsonClassGeneratorConfig config, StringBuilder sw, bool root) => sw.AppendLine("}");
|
|
|
|
public void WriteDeserializationComment(IJsonClassGeneratorConfig config, StringBuilder sw, bool rootIsArray = false)
|
|
{
|
|
_ = sw.AppendLine("// import com.fasterxml.jackson.databind.ObjectMapper; // version 2.11.1");
|
|
_ = sw.AppendLine("// import com.fasterxml.jackson.annotation.JsonProperty; // version 2.11.1");
|
|
_ = sw.AppendLine("/* ObjectMapper om = new ObjectMapper();");
|
|
|
|
if (rootIsArray)
|
|
{
|
|
_ = sw.AppendLine("Root[] root = om.readValue(myJsonString, Root[].class); */");
|
|
}
|
|
else
|
|
{
|
|
_ = sw.AppendLine("Root root = om.readValue(myJsonString, Root.class); */");
|
|
}
|
|
}
|
|
} |