176 lines
4.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace UniGLTF.JsonSchema.Schemas
{
public class ObjectJsonSchema : JsonSchemaBase
{
public string[] Required;
public readonly Dictionary<string, JsonSchemaBase> Properties = new Dictionary<string, JsonSchemaBase>();
bool m_useUpperCamelName;
public ObjectJsonSchema(in JsonSchemaSource source, bool useUpperCamelName) : base(source)
{
m_useUpperCamelName = useUpperCamelName;
foreach (var kv in source.EnumerateProperties())
{
var prop = kv.Value.Create(useUpperCamelName);
if (prop is null)
{
throw new NotImplementedException();
}
if (string.IsNullOrEmpty(prop.Title))
{
prop.Title = kv.Key.ToUpperCamel();
}
var key = kv.Key;
Properties.Add(key, prop);
}
Required = source.required;
}
public override string ToString()
{
var values = "";
if (Required != null && Required.Any())
{
values = $" require: {{{string.Join(", ", Required)}}}";
}
return $"{base.ToString()}{values}";
}
public override string ValueType => Title;
public override bool IsInline => false;
public override string GenerateDeserializerCall(string callName, string argName)
{
return $"{callName}({argName})";
}
public override void GenerateDeserializer(TraverseContext writer, string callName)
{
if (writer.Used.Contains(callName))
{
return;
}
writer.Used.Add(callName);
writer.Write(@"
public static $0 $2(JsonNode parsed)
{
var value = new $0();
foreach(var kv in parsed.ObjectItems())
{
var key = kv.Key.GetString();
"
.Replace("$0", ValueType)
.Replace("$2", callName)
);
var prefix = string.IsNullOrEmpty(ClassName) ? "Deserialize_" : $"{ClassName}_Deserialize_";
foreach (var kv in Properties)
{
writer.Write(@"
if(key==""$0""){
value.$2 = $1;
continue;
}
"
.Replace("$0", kv.Key)
.Replace("$1", kv.Value.GenerateDeserializerCall($"{prefix}{kv.Key.ToUpperCamel()}", "kv.Value"))
.Replace("$2", kv.Key.ToUpperCamel())
);
}
writer.Write(@"
}
return value;
}
");
foreach (var kv in Properties)
{
if (!kv.Value.IsInline)
{
kv.Value.GenerateDeserializer(writer, $"{prefix}{kv.Key.ToUpperCamel()}");
}
}
}
public override string CreateSerializationCondition(string argName)
{
return $"{argName}!=null";
}
/// <summary>
/// シリアライザーのコード生成
///
/// ObjectのFieldのみ値によって、出力するか否かの判定が必用。
///
/// 例: 空文字列は出力しない
///
/// </summary>
/// <param name="writer"></param>
/// <param name="callName"></param>
public override void GenerateSerializer(TraverseContext writer, string callName)
{
if (writer.Used.Contains(callName))
{
return;
}
writer.Used.Add(callName);
writer.Write($@"
public static void {callName}(JsonFormatter f, {ValueType} value)
{{
f.BeginMap();
"
);
var prefix = string.IsNullOrEmpty(ClassName) ? "Serialize_" : $"{ClassName}_Serialize_";
foreach (var kv in Properties)
{
var valueName = $"value.{kv.Key.ToUpperCamel()}";
var condition = "";
writer.Write($@"
if({kv.Value.CreateSerializationCondition(valueName)}{condition}){{
f.Key(""{kv.Key}"");
{kv.Value.GenerateSerializerCall($"{prefix}{kv.Key.ToUpperCamel()}", valueName)};
}}
");
}
writer.Write(@"
f.EndMap();
}
");
foreach (var kv in Properties)
{
if (!kv.Value.IsInline)
{
kv.Value.GenerateSerializer(writer, $"{prefix}{kv.Key.ToUpperCamel()}");
}
}
}
public override string GenerateSerializerCall(string callName, string argName)
{
return $"{callName}(f, {argName})";
}
}
}