Support dependencies of JsonSchema. Fix tests to compare values which using ToJson and using JsonSchema. Restrict valudator

This commit is contained in:
yutopp
2019-01-16 01:39:18 +09:00
parent da2f7b8490
commit 3516e488f1
6 changed files with 336 additions and 174 deletions

View File

@@ -150,7 +150,7 @@ namespace UniGLTF
[Test]
public void MeshTest()
{
var mesh = new glTFMesh("mesh")
var model = new glTFMesh("mesh")
{
primitives = new List<glTFPrimitives>
{
@@ -164,25 +164,22 @@ namespace UniGLTF
},
};
var f = new JsonFormatter();
f.Serialize(mesh);
var json = new Utf8String(f.GetStoreBytes()).ToString();
Assert.AreEqual(@"{""name"":""mesh"",""primitives"":[{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extensions"":{}}]}", json);
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""mesh"",""primitives"":[{""mode"":0,""indices"":-1,""attributes"":{""POSITION"":0},""material"":0}]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMesh>().Serialize(mesh, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFMesh>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""mesh"",""primitives"":[{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extensions"":{}}]}", json2);
}
[Test]
public void PrimitiveTest()
{
var prim = new glTFPrimitives
var model = new glTFPrimitives
{
attributes = new glTFAttributes
{
@@ -197,33 +194,27 @@ namespace UniGLTF
}
};
var f = new JsonFormatter();
f.Serialize(prim);
var json = new Utf8String(f.GetStoreBytes()).ToString();
Assert.AreEqual(@"{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]},""extensions"":{}}", json);
var json = model.ToJson();
Assert.AreEqual(@"{""mode"":0,""indices"":-1,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFPrimitives>().Serialize(prim, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFPrimitives>().Serialize(model, c);
Assert.AreEqual(@"{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]},""extensions"":{}}", json2);
}
[Test]
public void AttributesTest()
{
var attrs = new glTFAttributes
var model = new glTFAttributes
{
POSITION = 0,
};
var f = new JsonFormatter();
f.Serialize(attrs);
var json = new Utf8String(f.GetStoreBytes()).ToString();
var json = model.ToJson();
Assert.AreEqual(@"{""POSITION"":0}", json);
Debug.Log(json);
@@ -231,22 +222,19 @@ namespace UniGLTF
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFAttributes>().Serialize(attrs, c);
var json2 = JsonSchema.FromType<glTFAttributes>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void TextureInfoTest()
{
var texi = new glTFMaterialBaseColorTextureInfo()
var model = new glTFMaterialBaseColorTextureInfo()
{
index = 1,
};
var f = new JsonFormatter();
f.Serialize(texi);
var json = new Utf8String(f.GetStoreBytes()).ToString();
var json = model.ToJson();
Assert.AreEqual(@"{""index"":1,""texCoord"":0}", json);
Debug.Log(json);
@@ -254,21 +242,21 @@ namespace UniGLTF
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(texi, c);
var json2 = JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void TextureInfoTestError()
{
var texi = new glTFMaterialBaseColorTextureInfo();
var model = new glTFMaterialBaseColorTextureInfo();
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(texi, c)
() => JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(model, c)
);
Assert.AreEqual("[index.String] minimum: ! -1>=0", ex.Message);
}
@@ -276,25 +264,40 @@ namespace UniGLTF
[Test]
public void MaterialTest()
{
var texi = new glTFMaterial()
var model = new glTFMaterial()
{
name = "a",
emissiveFactor = new float[] { 0.5f, 0.5f, 0.5f },
};
var f = new JsonFormatter();
f.Serialize(texi);
var json = new Utf8String(f.GetStoreBytes()).ToString();
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""alphaCutoff"":0.5,""doubleSided"":false}", json);
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""doubleSided"":false}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMaterial>().Serialize(texi, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFMaterial>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""doubleSided"":false}", json2);
}
[Test]
public void MaterialAlphaTest()
{
var model = new glTFMaterial()
{
name = "a",
emissiveFactor = new float[] { 0.5f, 0.5f, 0.5f },
alphaMode = "MASK",
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json = JsonSchema.FromType<glTFMaterial>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""alphaMode"":""MASK"",""alphaCutoff"":0.5,""doubleSided"":false}", json);
}
[Test]
@@ -376,7 +379,7 @@ namespace UniGLTF
public void MaterialTestError()
{
var texi = new glTFMaterial()
var model = new glTFMaterial()
{
name = "b",
emissiveFactor = new float[] { 1.5f, 0.5f, 0.5f },
@@ -387,7 +390,7 @@ namespace UniGLTF
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFMaterial>().Serialize(texi, c)
() => JsonSchema.FromType<glTFMaterial>().Serialize(model, c)
);
Assert.AreEqual("[emissiveFactor.String] maximum: ! 1.5<=1", ex.Message);
}
@@ -395,32 +398,48 @@ namespace UniGLTF
[Test]
public void NodeTest()
{
var texi = new glTFNode()
var model = new glTFNode()
{
name = "a",
skin = 0,
camera = -1,
};
var f = new JsonFormatter();
f.Serialize(texi);
var json = new Utf8String(f.GetStoreBytes()).ToString();
Assert.AreEqual(@"{""name"":""a"",""skin"":0,""extras"":{}}", json);
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""a"",""skin"":0}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFNode>().Serialize(texi, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFNode>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""extras"":{}}", json2);
}
[Test]
public void NodeMeshTest()
{
var model = new glTFNode()
{
name = "a",
mesh = 2,
skin = 0,
camera = -1,
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json = JsonSchema.FromType<glTFNode>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""mesh"":2,""skin"":0,""extras"":{}}", json);
}
[Test]
public void NodeTestError()
{
var texi = new glTFNode()
var model = new glTFNode()
{
name = "a",
camera = -2,
@@ -431,7 +450,7 @@ namespace UniGLTF
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFNode>().Serialize(texi, c)
() => JsonSchema.FromType<glTFNode>().Serialize(model, c)
);
Assert.AreEqual("[camera.String] minimum: ! -2>=0", ex.Message);
}
@@ -439,56 +458,50 @@ namespace UniGLTF
[Test]
public void SkinTest()
{
var texi = new glTFSkin()
var model = new glTFSkin()
{
name = "b",
joints = new int[] {1},
};
var f = new JsonFormatter();
f.Serialize(texi);
var json = new Utf8String(f.GetStoreBytes()).ToString();
Assert.AreEqual(@"{""joints"":[1],""name"":""b""}", json);
var json = model.ToJson();
Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(texi, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(model, c);
Assert.AreEqual(@"{""joints"":[1],""name"":""b""}", json2);
}
[Test]
public void SkinTestEmptyName()
{
var texi = new glTFSkin()
var model = new glTFSkin()
{
name = "",
joints = new int[] {1},
};
var f = new JsonFormatter();
f.Serialize(texi);
var json = new Utf8String(f.GetStoreBytes()).ToString();
var json = model.ToJson();
// "name" = "", not excluded
Assert.AreEqual(@"{""joints"":[1],""name"":""""}", json);
Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(texi, c);
Assert.AreEqual(json, json2);
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(model, c);
Assert.AreEqual(@"{""joints"":[1],""name"":""""}", json2);
}
[Test]
public void SkinTestErrorNull()
{
var texi = new glTFSkin()
var model = new glTFSkin()
{
name = "b",
joints = null,
@@ -499,7 +512,7 @@ namespace UniGLTF
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFSkin>().Serialize(texi, c)
() => JsonSchema.FromType<glTFSkin>().Serialize(model, c)
);
Assert.AreEqual("[joints.String] null", ex.Message);
}
@@ -507,7 +520,7 @@ namespace UniGLTF
[Test]
public void SkinTestError()
{
var texi = new glTFSkin()
var model = new glTFSkin()
{
name = "b",
joints = new int[] {},
@@ -518,7 +531,7 @@ namespace UniGLTF
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFSkin>().Serialize(texi, c)
() => JsonSchema.FromType<glTFSkin>().Serialize(model, c)
);
Assert.AreEqual("[joints.String] minItems", ex.Message);
}

View File

@@ -10,7 +10,7 @@ namespace UniJSON
[JsonSchema(Minimum = 0)]
public int X;
[JsonSchema(Minimum = 10)] // Not required, thus ignored when the value violates the constraints
[JsonSchema(Minimum = 10, ExplicitIgnorableValue = 0)] // Not required, thus ignored when the value violates the constraints
public int Y;
}
@@ -77,5 +77,51 @@ namespace UniJSON
Assert.AreEqual(expected, actual);
}
public class HasDepsTest
{
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int X;
[JsonSchema(Dependencies = new string[] {"X"})]
public int Y;
}
[Test]
public void TestHasDeps()
{
var obj = new HasDepsTest();
var s = JsonSchema.FromType<HasDepsTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{""X"":0,""Y"":0}";
Assert.AreEqual(expected, actual);
}
[Test]
public void TestHasDepsHasViolation()
{
var obj = new HasDepsTest()
{
X = -1,
};
var s = JsonSchema.FromType<HasDepsTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{}";
Assert.AreEqual(expected, actual);
}
}
}

View File

@@ -354,7 +354,7 @@ namespace UniJSON
var s = JsonSchema.FromType<HasArrayOBject>();
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] {} }));
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { } }));
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { 0.5f } }));
Assert.NotNull(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { 1.5f } }));
@@ -379,12 +379,39 @@ namespace UniJSON
var s = JsonSchema.FromType<HasListObject>();
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> {} }));
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> { } }));
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> { 0.5f } }));
Assert.NotNull(s.Validator.Validate(c, new HasListObject { xs = new List<float> { 1.5f } }));
Assert.True(c.IsEmpty());
}
}
class HasRequiredListObject
{
[JsonSchema(Required = true, MinItems = 1)]
[ItemJsonSchema(Minimum = 0)]
public int[] xs;
}
[Test]
public void HasRequiredListObjecttValidator()
{
{
var c = new JsonSchemaValidationContext("test")
{
EnableDiagnosisForNotRequiredFields = true,
};
var s = JsonSchema.FromType<HasRequiredListObject>();
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject()));
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] {} }));
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] { -1 } }));
Assert.Null(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] { 0 } }));
Assert.True(c.IsEmpty());
}
}
}
}

View File

@@ -162,7 +162,14 @@ namespace UniJSON
{
// reflection
var schema = JsonSchema.FromType<T>();
return (IFormatter f, T value) => schema.Serialize(f, value);
return (IFormatter f, T value) =>
{
var c = new JsonSchemaValidationContext(value)
{
EnableDiagnosisForNotRequiredFields = true
};
schema.Serialize(f, value, c);
};
}

View File

@@ -392,7 +392,10 @@ namespace UniJSON
{
if (c == null)
{
c = new JsonSchemaValidationContext(o);
c = new JsonSchemaValidationContext(o)
{
EnableDiagnosisForNotRequiredFields = true,
};
}
var ex = Validator.Validate(c, o);

View File

@@ -297,28 +297,66 @@ namespace UniJSON
}
}
static class GenericFieldView<T>
{
public static FieldInfo[] GetFields()
{
var t = typeof(T);
return t.GetFields(BindingFlags.Instance | BindingFlags.Public);
}
public static void CreateFieldProcessors<G, D>(
string methodName,
Dictionary<string, D> processors
)
{
var mi = typeof(G).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);
var t = typeof(T);
foreach (var fi in GetFields())
{
var value = Expression.Parameter(t, "value");
var fieldValue = Expression.Field(value, fi);
var compileld = Expression.Lambda(fieldValue, value).Compile();
var getter = Expression.Constant(compileld);
var name = Expression.Constant(fi.Name);
var g = mi.MakeGenericMethod(fi.FieldType);
var call = Expression.Call(g, getter, name);
var lambda = (Func<D>)Expression.Lambda(call).Compile();
processors.Add(fi.Name, lambda());
}
}
}
internal class ValidationResult
{
public bool IsIgnorable;
public JsonSchemaValidationException Ex;
}
public static class GenericValidator<T>
{
class ObjectValidator
{
delegate JsonSchemaValidationException FieldValidator(
JsonSchema s, JsonSchemaValidationContext c, T o, bool isRequired);
JsonSchema s, JsonSchemaValidationContext c, T o, out bool isIgnorable);
Dictionary<string, FieldValidator> m_validators = new Dictionary<string, FieldValidator>();
Dictionary<string, FieldValidator> m_validators;
static FieldValidator CreteFieldValidator<U>(Func<T, U> getter, string name)
{
return (s, c, o, isRequired) =>
return (JsonSchema s, JsonSchemaValidationContext c, T o, out bool isIgnorable) =>
{
var v = s.Validator;
using (c.Push(name))
{
var field = getter(o);
var ex = v.Validate(c, field);
if (ex != null && !isRequired && s.IsExplicitlyIgnorableValue(field))
{
return null;
}
isIgnorable = ex != null && s.IsExplicitlyIgnorableValue(field);
return ex;
}
@@ -327,25 +365,46 @@ namespace UniJSON
public ObjectValidator()
{
var mi = typeof(ObjectValidator).GetMethod("CreteFieldValidator",
BindingFlags.Static|BindingFlags.NonPublic);
var validators = new Dictionary<string, FieldValidator>();
GenericFieldView<T>.CreateFieldProcessors<ObjectValidator, FieldValidator>(
"CreteFieldValidator", validators);
var t = typeof(T);
foreach(var fi in t.GetFields(
BindingFlags.Instance|BindingFlags.Public))
m_validators = validators;
}
public JsonSchemaValidationException ValidateProperty(
HashSet<string> required,
KeyValuePair<string, JsonSchema> property,
JsonSchemaValidationContext c,
T o,
out bool isIgnorable
)
{
var fieldName = property.Key;
var schema = property.Value;
isIgnorable = false;
FieldValidator fv;
if (m_validators.TryGetValue(fieldName, out fv))
{
var value = Expression.Parameter(typeof(T), "value");
var fieldValue = Expression.Field(value, fi);
var compileld = Expression.Lambda(fieldValue, value).Compile();
var isRequired = required != null && required.Contains(fieldName);
var getter = Expression.Constant(compileld);
var name = Expression.Constant(fi.Name);
var g = mi.MakeGenericMethod(fi.FieldType);
var call = Expression.Call(g, getter, name);
var lambda = (Func<FieldValidator>)Expression.Lambda(call).Compile();
bool isMemberIgnorable;
var ex = fv(schema, c, o, out isMemberIgnorable);
if (ex != null)
{
isIgnorable = !isRequired && isMemberIgnorable;
m_validators.Add(fi.Name, lambda());
if (isRequired // required fields must be checked
|| c.EnableDiagnosisForNotRequiredFields)
{
return ex;
}
}
}
return null;
}
public JsonSchemaValidationException Validate(
@@ -355,41 +414,62 @@ namespace UniJSON
{
foreach (var kv in properties)
{
var fieldName = kv.Key;
var schema = kv.Value;
FieldValidator fv;
if (m_validators.TryGetValue(fieldName, out fv))
bool isIgnorable;
var ex = ValidateProperty(required, kv, c, o, out isIgnorable);
if (ex != null && !isIgnorable)
{
var isRequired = required != null && required.Contains(fieldName);
var ex = fv(schema, c, o, isRequired);
if (ex != null)
{
if (isRequired // required fields must be checked
|| c.EnableDiagnosisForNotRequiredFields)
{
return ex;
}
}
return ex;
}
}
return null;
}
public void ValidationResults
(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o,
Dictionary<string, ValidationResult> results)
{
foreach (var kv in properties)
{
bool isIgnorable;
var ex = ValidateProperty(required, kv, c, o, out isIgnorable);
results.Add(kv.Key, new ValidationResult {
IsIgnorable = isIgnorable,
Ex = ex,
});
}
}
}
static ObjectValidator s_validator;
public static JsonSchemaValidationException Validate(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o)
static void prepareValidator()
{
if (s_validator == null)
{
s_validator = new ObjectValidator();
}
}
public static JsonSchemaValidationException Validate(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o)
{
prepareValidator();
return s_validator.Validate(required, properties, c, o);
}
internal static void ValidationResults(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o,
Dictionary<string, ValidationResult> results)
{
prepareValidator();
s_validator.ValidationResults(required, properties, c, o, results);
}
}
public JsonSchemaValidationException Validate<T>(JsonSchemaValidationContext c, T o)
@@ -411,103 +491,89 @@ namespace UniJSON
{
class Serializer
{
delegate void FieldSerializer(JsonObjectValidator v, IFormatter f, JsonSchemaValidationContext c, T src);
delegate void FieldSerializer(JsonSchema s, JsonSchemaValidationContext c, IFormatter f, T o,
Dictionary<string, ValidationResult> vRes, string[] deps);
List<FieldSerializer> m_fieldSerializers = new List<FieldSerializer>();
Dictionary<string, FieldSerializer> m_serializers;
static FieldSerializer CreateSerializer<U>(FieldInfo fi)
static FieldSerializer CreteFieldSerializer<U>(Func<T, U> getter, string name)
{
var src = Expression.Parameter(typeof(T), "src");
var getter = Expression.Field(src, fi);
var compiled = (Func<T, U>)Expression.Lambda(getter, src).Compile();
var name = fi.Name;
return (v, f, c, s) =>
return (s, c, f, o, vRes, deps) =>
{
//c.Push(name);
var v = s.Validator;
var field = getter(o);
var validator = v.Properties[name].Validator;
var value = compiled(s);
// validate
if (validator.Validate(c, value) != null)
if (vRes[name].Ex != null)
{
return;
}
/*
// depencencies
string[] dependencies;
if (validator.Dependencies.TryGetValue(name, out dependencies))
if (deps != null)
{
// check dependencies
bool hasDependencies = true;
foreach (var x in dependencies)
foreach(var dep in deps)
{
if (!map.ContainsKey(x))
if (vRes[dep].Ex != null)
{
hasDependencies = false;
break;
return;
}
}
if (!hasDependencies)
{
continue;
}
}
*/
f.Key(name);
validator.Serialize(f, c, value);
//f.Serialize(value);
//c.Pop();
v.Serialize(f, c, field);
};
}
public void AddField(FieldInfo fi)
public Serializer()
{
var mi = typeof(Serializer).GetMethod("CreateSerializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(fi.FieldType);
var f = Expression.Constant(fi);
var call = Expression.Call(g, f);
var compiled = (Func<FieldSerializer>)Expression.Lambda(call).Compile();
m_fieldSerializers.Add(compiled());
var serializers = new Dictionary<string, FieldSerializer>();
GenericFieldView<T>.CreateFieldProcessors<Serializer, FieldSerializer>(
"CreteFieldSerializer", serializers);
m_serializers = serializers;
}
public void Serialize(JsonObjectValidator v, IFormatter f, JsonSchemaValidationContext c, T value)
public void Serialize(JsonObjectValidator objectValidator,
IFormatter f, JsonSchemaValidationContext c, T o)
{
f.BeginMap(m_fieldSerializers.Count);
foreach (var s in m_fieldSerializers)
// Validates fields
var validationResults = new Dictionary<string, ValidationResult>();
GenericValidator<T>.ValidationResults(
objectValidator.Required, objectValidator.Properties,
c, o, validationResults);
// Serialize fields
f.BeginMap(objectValidator.Properties.Count());
foreach (var property in objectValidator.Properties)
{
s(v, f, c, value);
var fieldName = property.Key;
var schema = property.Value;
string[] deps = null;
objectValidator.Dependencies.TryGetValue(fieldName, out deps);
FieldSerializer fs;
if (m_serializers.TryGetValue(fieldName, out fs))
{
fs(schema, c, f, o, validationResults, deps);
}
}
f.EndMap();
}
}
static FieldInfo[] s_fields;
static Serializer s_serializer;
public static void Serialize(JsonObjectValidator validator,
public static void Serialize(JsonObjectValidator objectValidator,
IFormatter f, JsonSchemaValidationContext c, T value)
{
if (s_serializer == null)
{
var t = typeof(T);
if (t == typeof(object))
{
throw new ArgumentException("object cannot serialize");
}
var serializer = new Serializer();
var fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var fi in fields)
{
serializer.AddField(fi);
}
s_serializer = serializer;
s_serializer = new Serializer();
}
s_serializer.Serialize(validator, f, c, value);
s_serializer.Serialize(objectValidator, f, c, value);
}
}