using System; using System.Linq; using System.Collections.Generic; namespace UniJSON { /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5 /// public class JsonDictionaryValidator : IJsonSchemaValidator { public JsonDictionaryValidator() { AdditionalProperties = JsonSchema.FromType(); } /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.1 /// public int MaxProperties { get; set; } /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.2 /// public int MinProperties { get; set; } List m_required = new List(); /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.3 /// public List Required { get { return m_required; } } /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.5 /// public string PatternProperties { get; private set; } /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.6 /// public JsonSchema AdditionalProperties { get; set; } Dictionary m_depndencies; /// /// http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.5.7 /// public Dictionary Dependencies { get { if (m_depndencies == null) { m_depndencies = new Dictionary(); } return m_depndencies; } } public override int GetHashCode() { return 6; } public override bool Equals(object obj) { var rhs = obj as JsonObjectValidator; if (rhs == null) { return false; } if (Required.Count != rhs.Required.Count) { return false; } if (!Required.OrderBy(x => x).SequenceEqual(rhs.Required.OrderBy(x => x))) { return false; } if (Dependencies.Count != rhs.Dependencies.Count) { return false; } foreach (var kv in Dependencies) { if (!kv.Value.OrderBy(x => x).SequenceEqual(rhs.Dependencies[kv.Key].OrderBy(x => x))) { return false; } } if (AdditionalProperties == null && rhs.AdditionalProperties == null) { // ok } else if (AdditionalProperties == null) { return false; } else if (rhs.AdditionalProperties == null) { return false; } else { if (!AdditionalProperties.Equals(rhs.AdditionalProperties)) { return false; } } return true; } public void Assign(IJsonSchemaValidator obj) { var rhs = obj as JsonObjectValidator; if (rhs == null) { throw new ArgumentException(); } foreach (var x in rhs.Required) { this.Required.Add(x); } if (rhs.AdditionalProperties != null) { if (AdditionalProperties != null) { throw new NotImplementedException(); } AdditionalProperties = rhs.AdditionalProperties; } } public bool Parse(IFileSystemAccessor fs, string key, JsonNode value) { switch (key) { case "maxProperties": MaxProperties = value.GetInt32(); return true; case "minProperties": MinProperties = value.GetInt32(); return true; case "required": { foreach (var req in value.ArrayItems) { m_required.Add(req.GetString()); } } return true; case "patternProperties": PatternProperties = value.GetString(); return true; case "additionalProperties": { var sub = new JsonSchema(); sub.Parse(fs, value, "additionalProperties"); AdditionalProperties = sub; } return true; case "dependencies": { foreach (var kv in value.ObjectItems) { Dependencies.Add(kv.Key, kv.Value.ArrayItems.Select(x => x.GetString()).ToArray()); } } return true; case "propertyNames": return true; } return false; } public JsonSchemaValidationException Validate(JsonSchemaValidationContext c, object o) { if (o == null) { return new JsonSchemaValidationException(c, "null"); } if (Required != null) { foreach (var x in Required) { using (c.Push(x)) { /*var value =*/ o.GetValueByKey(x); } } } return null; } Dictionary m_validValueMap = new Dictionary(); public void Serialize(JsonFormatter f, JsonSchemaValidationContext c, Object o) { // validate properties m_validValueMap.Clear(); using (f.BeginMapDisposable()) { var dict = o as Dictionary; foreach (var kv in dict) { // key f.Key(kv.Key); // value using (c.Push(kv.Key)) { AdditionalProperties.Validator.Serialize(f, c, kv.Value); } } } } public void ToJson(JsonFormatter f) { f.Key("type"); f.Value("object"); } } public static class JsonDictionaryValidator { public static JsonDictionaryValidator Create() { return new JsonDictionaryValidator(); } } }