From 77eaa4bcb022d5958526cbf350a9084fceb7049d Mon Sep 17 00:00:00 2001 From: yutopp Date: Tue, 8 Jan 2019 23:28:02 +0900 Subject: [PATCH] Add/Fix tests for UniJSON. Add ExplicitIgnorableValue option to ignore checks for validations --- .../Editor/Tests/Json/JsonSerializerTests.cs | 3 +- .../UniJSON/Editor/Tests/Json/SchemaTests.cs | 26 ++++++++-- .../Tests/Json/SerializeWithSchemaTests.cs | 43 +++++++++++++++ .../Editor/Tests/Json/ValidatorTests.cs | 52 ++++++++++++++++++- Assets/VRM/UniJSON/Scripts/Json/JsonSchema.cs | 15 +++++- .../Scripts/Json/JsonSchemaAttribute.cs | 6 +++ .../JsonObjectValidator.cs | 24 ++++++--- 7 files changed, 152 insertions(+), 17 deletions(-) diff --git a/Assets/VRM/UniJSON/Editor/Tests/Json/JsonSerializerTests.cs b/Assets/VRM/UniJSON/Editor/Tests/Json/JsonSerializerTests.cs index 767e55505..0f497e9fb 100644 --- a/Assets/VRM/UniJSON/Editor/Tests/Json/JsonSerializerTests.cs +++ b/Assets/VRM/UniJSON/Editor/Tests/Json/JsonSerializerTests.cs @@ -28,7 +28,7 @@ namespace UniJSON } struct EnumTest - { + { public HogeFuga EnumDefault; [JsonSchema(EnumSerializationType =EnumSerializationType.AsInt)] @@ -104,6 +104,7 @@ namespace UniJSON Assert.AreEqual(1, json.GetObjectCount()); Assert.AreEqual(1, json["Vector"][0].GetInt32()); } + #endregion #region Deserialize diff --git a/Assets/VRM/UniJSON/Editor/Tests/Json/SchemaTests.cs b/Assets/VRM/UniJSON/Editor/Tests/Json/SchemaTests.cs index 66daa11a3..1f51b07a0 100644 --- a/Assets/VRM/UniJSON/Editor/Tests/Json/SchemaTests.cs +++ b/Assets/VRM/UniJSON/Editor/Tests/Json/SchemaTests.cs @@ -1,7 +1,6 @@ #pragma warning disable 0649 using NUnit.Framework; - namespace UniJSON { public class SchemaTests @@ -40,6 +39,24 @@ namespace UniJSON Assert.AreEqual(0, parsed["properties"]["age"]["minimum"].GetInt32()); } + [JsonSchema(Title="MultipleConstraints")] + public class MultipleConstraints + { + [JsonSchema(Required = true, Minimum = 0, Maximum = 100)] + public int ranged; + } + + [Test] + public void CreateFromClassWithMultipleConstraints() + { + var s = JsonSchema.FromType(); + + var v = s.Validator as JsonObjectValidator; + var rangedV = v.Properties["ranged"].Validator as JsonIntValidator; + Assert.AreEqual(0, rangedV.Minimum); + Assert.AreEqual(100, rangedV.Maximum); + } + public enum ProjectionType { Perspective, @@ -48,7 +65,7 @@ namespace UniJSON class EnumStringTest { - [JsonSchema(EnumSerializationType =EnumSerializationType.AsLowerString)] + [JsonSchema(EnumSerializationType = EnumSerializationType.AsLowerString)] public ProjectionType type; } @@ -81,7 +98,7 @@ namespace UniJSON ] } - + } } "; @@ -117,7 +134,7 @@ namespace UniJSON ] } - + } } "; @@ -129,6 +146,5 @@ namespace UniJSON Assert.AreEqual(fromJson, fromType); } - } } diff --git a/Assets/VRM/UniJSON/Editor/Tests/Json/SerializeWithSchemaTests.cs b/Assets/VRM/UniJSON/Editor/Tests/Json/SerializeWithSchemaTests.cs index 5d0556954..e5aacd5cb 100644 --- a/Assets/VRM/UniJSON/Editor/Tests/Json/SerializeWithSchemaTests.cs +++ b/Assets/VRM/UniJSON/Editor/Tests/Json/SerializeWithSchemaTests.cs @@ -34,5 +34,48 @@ namespace UniJSON Assert.AreEqual(expected, actual); } + + [JsonSchema(Title="ObjectNestedTest")] + public class ObjectNestedTest + { + public CheckConstraintsTest C; + } + + [Test] + public void TestObjectNested() + { + var obj = new ObjectNestedTest() + { + C = new CheckConstraintsTest(), + }; + + var s = JsonSchema.FromType(); + { + var c = new JsonSchemaValidationContext(obj); + Assert.Null(s.Validator.Validate(c, s)); + } + var actual = s.Serialize(obj); + + var expected = @"{""C"":{""X"":0}}"; + + Assert.AreEqual(expected, actual); + } + + [Test] + public void TestObjectNestedWithNull() + { + var obj = new ObjectNestedTest(); + + var s = JsonSchema.FromType(); + { + var c = new JsonSchemaValidationContext(obj); + Assert.Null(s.Validator.Validate(c, s)); + } + var actual = s.Serialize(obj); + + var expected = @"{}"; + + Assert.AreEqual(expected, actual); + } } } diff --git a/Assets/VRM/UniJSON/Editor/Tests/Json/ValidatorTests.cs b/Assets/VRM/UniJSON/Editor/Tests/Json/ValidatorTests.cs index 7165a3d37..fc50234b3 100644 --- a/Assets/VRM/UniJSON/Editor/Tests/Json/ValidatorTests.cs +++ b/Assets/VRM/UniJSON/Editor/Tests/Json/ValidatorTests.cs @@ -216,7 +216,7 @@ namespace UniJSON var s = JsonSchema.FromType(); // An error is not returned because Value is not 'Required' and the diagnosis is not enabled - Assert.Null(s.Validator.Validate(c, new Hoge { Value = 0 })); + Assert.Null(s.Validator.Validate(c, new NotRequired { Value = 0 })); Assert.True(c.IsEmpty()); } @@ -228,7 +228,55 @@ namespace UniJSON }; var s = JsonSchema.FromType(); - Assert.NotNull(s.Validator.Validate(c, new Hoge { Value = 0 })); + Assert.NotNull(s.Validator.Validate(c, new NotRequired { Value = 0 })); + + Assert.True(c.IsEmpty()); + } + } + + class NotRequiredWithIgnorable + { + [JsonSchema(Minimum = 2, ExplicitIgnorableValue = -1)] + public int Value; + } + + [Test] + public void ObjectValidatorForNotRequiredWithIgnorable() + { + { + var c = new JsonSchemaValidationContext("test") + { + EnableDiagnosisForNotRequiredFields = false, // Default behaviour + }; + + var s = JsonSchema.FromType(); + // An error is not returned because Value is not 'Required' and the diagnosis is not enabled + Assert.Null(s.Validator.Validate(c, new NotRequiredWithIgnorable { Value = 0 })); + + Assert.True(c.IsEmpty()); + } + + { + var c = new JsonSchemaValidationContext("test") + { + EnableDiagnosisForNotRequiredFields = true, + }; + + var s = JsonSchema.FromType(); + Assert.NotNull(s.Validator.Validate(c, new NotRequiredWithIgnorable { Value = 0 })); + + Assert.True(c.IsEmpty()); + } + + { + var c = new JsonSchemaValidationContext("test") + { + EnableDiagnosisForNotRequiredFields = true, + }; + + var s = JsonSchema.FromType(); + // An error is NOT returned even though diagnosis is enabled because of an ignorable value is matched + Assert.Null(s.Validator.Validate(c, new NotRequiredWithIgnorable { Value = -1 })); Assert.True(c.IsEmpty()); } diff --git a/Assets/VRM/UniJSON/Scripts/Json/JsonSchema.cs b/Assets/VRM/UniJSON/Scripts/Json/JsonSchema.cs index 7adfe12e4..be73d4102 100644 --- a/Assets/VRM/UniJSON/Scripts/Json/JsonSchema.cs +++ b/Assets/VRM/UniJSON/Scripts/Json/JsonSchema.cs @@ -57,6 +57,8 @@ namespace UniJSON /// public bool SkipComparison { get; set; } + public object ExplicitIgnorableValue { private get; set; } + public override string ToString() { return string.Format("<{0}>", Title); @@ -175,7 +177,8 @@ namespace UniJSON Title = a.Title, Description = a.Description, Validator = validator, - SkipComparison = skipComparison + SkipComparison = skipComparison, + ExplicitIgnorableValue = a.ExplicitIgnorableValue, }; return schema; @@ -404,6 +407,16 @@ namespace UniJSON Validator.ToJsonScheama(f); f.EndMap(); } + + public bool IsExplicitlyIgnorableValue(T obj) + { + if (obj == null) + { + return ExplicitIgnorableValue == null; + } + + return obj.Equals(ExplicitIgnorableValue); + } } public static class JsonSchemaExtensions diff --git a/Assets/VRM/UniJSON/Scripts/Json/JsonSchemaAttribute.cs b/Assets/VRM/UniJSON/Scripts/Json/JsonSchemaAttribute.cs index 4171769f1..f7ebad56a 100644 --- a/Assets/VRM/UniJSON/Scripts/Json/JsonSchemaAttribute.cs +++ b/Assets/VRM/UniJSON/Scripts/Json/JsonSchemaAttribute.cs @@ -55,6 +55,12 @@ namespace UniJSON /// public bool SkipSchemaComparison; + /// + /// Suppress errors if a value of the field which is not required by a schema is matched to this value. + /// This feature will be useful to ignore invalid value which is known. + /// + public object ExplicitIgnorableValue; + public void Merge(BaseJsonSchemaAttribute rhs) { if (rhs == null) return; diff --git a/Assets/VRM/UniJSON/Scripts/JsonSchemaValidator/JsonObjectValidator.cs b/Assets/VRM/UniJSON/Scripts/JsonSchemaValidator/JsonObjectValidator.cs index a4dd1e8e6..c0b65b0eb 100644 --- a/Assets/VRM/UniJSON/Scripts/JsonSchemaValidator/JsonObjectValidator.cs +++ b/Assets/VRM/UniJSON/Scripts/JsonSchemaValidator/JsonObjectValidator.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; - namespace UniJSON { /// @@ -302,18 +301,26 @@ namespace UniJSON { class ObjectValidator { - delegate JsonSchemaValidationException FieldValidator(IJsonSchemaValidator v, - JsonSchemaValidationContext c, T o); + delegate JsonSchemaValidationException FieldValidator( + JsonSchema s, JsonSchemaValidationContext c, T o, bool isRequired); Dictionary m_validators = new Dictionary(); static FieldValidator CreteFieldValidator(Func getter, string name) { - return (v, c, o) => + return (s, c, o, isRequired) => { + var v = s.Validator; using (c.Push(name)) { - return v.Validate(c, getter(o)); + var field = getter(o); + var ex = v.Validate(c, field); + if (ex != null && !isRequired && s.IsExplicitlyIgnorableValue(field)) + { + return null; + } + + return ex; } }; } @@ -354,11 +361,12 @@ namespace UniJSON FieldValidator fv; if (m_validators.TryGetValue(fieldName, out fv)) { - var ex = fv(schema.Validator, c, o); + var isRequired = required.Contains(fieldName); + var ex = fv(schema, c, o, isRequired); if (ex != null) { - if (required.Contains(fieldName) // required fields must be checked - || c.EnableDiagnosisForNotRequiredFields) + if (isRequired // required fields must be checked + || c.EnableDiagnosisForNotRequiredFields) { return ex; }