diff options
Diffstat (limited to 'Assets/ThirdParty/VRM/VRM/UniJSON/Scripts/Json/JsonSchema.cs')
| -rw-r--r-- | Assets/ThirdParty/VRM/VRM/UniJSON/Scripts/Json/JsonSchema.cs | 445 | 
1 files changed, 445 insertions, 0 deletions
diff --git a/Assets/ThirdParty/VRM/VRM/UniJSON/Scripts/Json/JsonSchema.cs b/Assets/ThirdParty/VRM/VRM/UniJSON/Scripts/Json/JsonSchema.cs new file mode 100644 index 00000000..6e573467 --- /dev/null +++ b/Assets/ThirdParty/VRM/VRM/UniJSON/Scripts/Json/JsonSchema.cs @@ -0,0 +1,445 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace UniJSON +{ +    public class JsonSchema : IEquatable<JsonSchema> +    { +        public string Schema; // http://json-schema.org/draft-04/schema + +        #region Annotations +        string m_title; +        public string Title +        { +            get { return m_title; } +            private set +            { +                if (value == null) +                { +                    m_title = ""; +                } +                else +                { +                    m_title = value.Trim(); +                } +            } +        } + +        string m_desc; +        public string Description +        { +            get { return m_desc; } +            private set +            { +                if (value == null) +                { +                    m_desc = ""; +                } +                else +                { +                    m_desc = value.Trim(); +                } +            } +        } + +        public object Default +        { +            get; +            private set; +        } +        #endregion + +        public IJsonSchemaValidator Validator { get; set; } + +        /// <summary> +        /// Skip validator comparison +        /// </summary> +        public bool SkipComparison { get; set; } + +        public object ExplicitIgnorableValue { private get; set; } +        public int ExplicitIgnorableItemLength { private get; set; } + +        public override string ToString() +        { +            return string.Format("<{0}>", Title); +        } + +        public override int GetHashCode() +        { +            return 1; +        } + +        public override bool Equals(object obj) +        { +            var rhs = obj as JsonSchema; +            if (rhs == null) return false; +            return Equals(rhs); +        } + +        public bool Equals(JsonSchema rhs) +        { +            // skip comparison +            if (SkipComparison) return true; +            if (rhs.SkipComparison) return true; +            return Validator.Equals(rhs.Validator); +        } + +        public static bool operator ==(JsonSchema obj1, JsonSchema obj2) +        { +            if (ReferenceEquals(obj1, obj2)) +            { +                return true; +            } + +            if (ReferenceEquals(obj1, null)) +            { +                return false; +            } + +            if (ReferenceEquals(obj2, null)) +            { +                return false; +            } + +            return obj1.Equals(obj2); +        } + +        public static bool operator !=(JsonSchema obj1, JsonSchema obj2) +        { +            return !(obj1 == obj2); +        } + +        #region FromType +        public static JsonSchema FromType<T>() +        { +            return FromType(typeof(T), null, null); +        } + +        public static JsonSchema FromType(Type t, +            BaseJsonSchemaAttribute a = null, // field attribute +            ItemJsonSchemaAttribute ia = null +            ) +        { +            // class attribute +            var aa = t.GetCustomAttributes(typeof(JsonSchemaAttribute), true) +                .FirstOrDefault() as JsonSchemaAttribute; +            if (a != null) +            { +                a.Merge(aa); +            } +            else +            { +                if (aa == null) +                { +                    a = new JsonSchemaAttribute(); +                } +                else +                { +                    a = aa; +                } +            } + +            if (ia == null) +            { +                ia = t.GetCustomAttributes(typeof(ItemJsonSchemaAttribute), true) +                    .FirstOrDefault() as ItemJsonSchemaAttribute; +            } + +            IJsonSchemaValidator validator = null; +            bool skipComparison = a.SkipSchemaComparison; +            if (t == typeof(object)) +            { +                skipComparison = true; +            } + +            if (a.EnumValues != null) +            { +                try +                { +                    validator = JsonEnumValidator.Create(a.EnumValues, a.EnumSerializationType); +                } +                catch (Exception) +                { +                    throw new Exception(String.Join(", ", a.EnumValues.Select(x => x.ToString()).ToArray())); +                } +            } +            else if (t.IsEnum) +            { +                validator = JsonEnumValidator.Create(t, a.EnumSerializationType, a.EnumExcludes); +            } +            else +            { +                validator = JsonSchemaValidatorFactory.Create(t, a, ia); +            } + +            var schema = new JsonSchema +            { +                Title = a.Title, +                Description = a.Description, +                Validator = validator, +                SkipComparison = skipComparison, +                ExplicitIgnorableValue = a.ExplicitIgnorableValue, +                ExplicitIgnorableItemLength = a.ExplicitIgnorableItemLength, +            }; + +            return schema; +        } +        #endregion + +        #region FromJson +        static ValueNodeType ParseValueType(string type) +        { +            try +            { +                return (ValueNodeType)Enum.Parse(typeof(ValueNodeType), type, true); +            } +            catch (ArgumentException) +            { +                throw new ArgumentException(string.Format("unknown type: {0}", type)); +            } +        } + +        Stack<string> m_context = new Stack<string>(); + +        static Utf8String s_ref = Utf8String.From("$ref"); + +        public void Parse(IFileSystemAccessor fs, ListTreeNode<JsonValue> root, string Key) +        { +            m_context.Push(Key); + +            var compositionType = default(CompositionType); +            var composition = new List<JsonSchema>(); +            foreach (var kv in root.ObjectItems()) +            { +                switch (kv.Key.GetString()) +                { +                    case "$schema": +                        Schema = kv.Value.GetString(); +                        break; + +                    case "$ref": +                        { +                            var refFs = fs.Get(kv.Value.GetString()); + +                            // parse JSON +                            var json = refFs.ReadAllText(); +                            var refRoot = JsonParser.Parse(json); + +                            Parse(refFs, refRoot, "$ref"); +                        } +                        break; + +                    #region Annotation +                    case "title": +                        Title = kv.Value.GetString(); +                        break; + +                    case "description": +                        Description = kv.Value.GetString(); +                        break; + +                    case "default": +                        Default = kv.Value; +                        break; +                    #endregion + +                    #region Validation +                    // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1 +                    case "type": +                        if (Validator == null) +                        { +                            Validator = JsonSchemaValidatorFactory.Create(kv.Value.GetString()); +                        } +                        break; + +                    case "enum": +                        Validator = JsonEnumValidator.Create(kv.Value); +                        break; + +                    case "const": +                        break; +                    #endregion + +                    #region Composite +                    // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.7 +                    case "oneOf": +                        break; + +                    case "not": +                        break; + +                    case "anyOf": // composition +                    case "allOf": // composition +                        { +                            compositionType = (CompositionType)Enum.Parse(typeof(CompositionType), kv.Key.GetString(), true); +                            foreach (var item in kv.Value.ArrayItems()) +                            { +                                if (item.ContainsKey(s_ref)) +                                { +                                    var sub = JsonSchema.ParseFromPath(fs.Get(item[s_ref].GetString())); +                                    composition.Add(sub); +                                } +                                else +                                { +                                    var sub = new JsonSchema(); +                                    sub.Parse(fs, item, compositionType.ToString()); +                                    composition.Add(sub); +                                } +                            } +                            Composite(compositionType, composition); +                        } +                        break; +                    #endregion + +                    // http://json-schema.org/latest/json-schema-validation.html#rfc.section.7 +                    case "format": +                        break; + +                    #region Gltf +                    case "gltf_detailedDescription": +                        break; + +                    case "gltf_webgl": +                        break; + +                    case "gltf_uriType": +                        break; +                    #endregion + +                    default: +                        { +                            if (Validator != null) +                            { +                                if (Validator.FromJsonSchema(fs, kv.Key.GetString(), kv.Value)) +                                { +                                    continue; +                                } +                            } +                            throw new NotImplementedException(string.Format("unknown key: {0}", kv.Key)); +                        } +                } +            } +            m_context.Pop(); + +            if (Validator == null) +            { +                SkipComparison = true; +            } +        } + +        void Composite(CompositionType compositionType, List<JsonSchema> composition) +        { +            switch (compositionType) +            { +                case CompositionType.AllOf: +                    if (composition.Count == 1) +                    { +                        // inheritance +                        if (Validator == null) +                        { +                            //Validator = JsonSchemaValidatorFactory.Create(composition[0].Validator.ValueNodeType); +                            Validator = composition[0].Validator; +                        } +                        else +                        { +                            Validator.Merge(composition[0].Validator); +                        } +                    } +                    else +                    { +                        throw new NotImplementedException(); +                    } +                    break; + +                case CompositionType.AnyOf: +                    if (Validator == null) +                    { +                        if (composition.Count == 1) +                        { +                            throw new NotImplementedException(); +                            //Validator = composition[0].Validator; +                        } +                        else +                        { +                            // extend enum +                            // enum, enum..., type +                            Validator = JsonEnumValidator.Create(composition, EnumSerializationType.AsString); +                        } +                    } +                    //throw new NotImplementedException(); +                    break; + +                default: +                    throw new NotImplementedException(); +            } +        } + +        public static JsonSchema ParseFromPath(IFileSystemAccessor fs) +        { +            // parse JSON +            var json = fs.ReadAllText(); +            var root = JsonParser.Parse(json); + +            // create schema +            var schema = new JsonSchema(); +            schema.Parse(fs, root, "__ParseFromPath__" + fs.ToString()); +            return schema; +        } +        #endregion + +        public void Serialize<T>(IFormatter f, T o, JsonSchemaValidationContext c = null) +        { +            if (c == null) +            { +                c = new JsonSchemaValidationContext(o) +                { +                    EnableDiagnosisForNotRequiredFields = true, +                }; +            } + +            var ex = Validator.Validate(c, o); +            if (ex != null) +            { +                throw ex; +            } + +            Validator.Serialize(f, c, o); +        } + +        public void ToJson(IFormatter f) +        { +            f.BeginMap(2); +            if (!string.IsNullOrEmpty(Title)) { f.Key("title"); f.Value(Title); } +            if (!string.IsNullOrEmpty(Description)) { f.Key("description"); f.Value(Description); } +            Validator.ToJsonSchema(f); +            f.EndMap(); +        } + +        public bool IsExplicitlyIgnorableValue<T>(T obj) +        { +            if (obj == null) +            { +                return ExplicitIgnorableValue == null; +            } + +            var iter = obj as System.Collections.ICollection; +            if (ExplicitIgnorableItemLength != -1 && iter != null) +            { +                return iter.Count == ExplicitIgnorableItemLength; +            } + +            return obj.Equals(ExplicitIgnorableValue); +        } +    } + +    public static class JsonSchemaExtensions +    { +        public static string Serialize<T>(this JsonSchema s, T o, JsonSchemaValidationContext c = null) +        { +            var f = new JsonFormatter(); +            s.Serialize(f, o, c); +            return f.ToString(); +        } +    } +}  | 
