Example #1
0
        private JsonSchema BuildSchema()
        {
            if (_reader.TokenType != JsonToken.StartObject)
            {
                throw new Exception("Expected StartObject while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, _reader.TokenType));
            }

            _reader.Read();
            // empty schema object
            if (_reader.TokenType == JsonToken.EndObject)
            {
                Push(new JsonSchema());
                return(Pop());
            }

            string propertyName = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture);

            _reader.Read();

            // schema reference
            if (propertyName == JsonSchemaConstants.ReferencePropertyName)
            {
                string id = (string)_reader.Value;

                // skip to the end of the current object
                while (_reader.Read() && _reader.TokenType != JsonToken.EndObject)
                {
                    if (_reader.TokenType == JsonToken.StartObject)
                    {
                        throw new Exception("Found StartObject within the schema reference with the Id '{0}'"
                                            .FormatWith(CultureInfo.InvariantCulture, id));
                    }
                }

                JsonSchema referencedSchema = _resolver.GetSchema(id);
                if (referencedSchema == null)
                {
                    throw new Exception("Could not resolve schema reference for Id '{0}'.".FormatWith(CultureInfo.InvariantCulture, id));
                }

                return(referencedSchema);
            }

            // regular ol' schema object
            Push(new JsonSchema());

            ProcessSchemaProperty(propertyName);

            while (_reader.Read() && _reader.TokenType != JsonToken.EndObject)
            {
                propertyName = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture);
                _reader.Read();

                ProcessSchemaProperty(propertyName);
            }

            return(Pop());
        }
Example #2
0
 private void ReferenceOrWriteSchema(JsonSchema schema)
 {
     if (schema.Id != null && _resolver.GetSchema(schema.Id) != null)
     {
         _writer.WriteStartObject();
         _writer.WritePropertyName(JsonSchemaConstants.ReferencePropertyName);
         _writer.WriteValue(schema.Id);
         _writer.WriteEndObject();
     }
     else
     {
         WriteSchema(schema);
     }
 }
        private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required)
        {
            ValidationUtils.ArgumentNotNull(type, "type");

            string resolvedId = GetTypeId(type, false);
            string explicitId = GetTypeId(type, true);

            if (!string.IsNullOrEmpty(resolvedId))
            {
                JsonSchema resolvedSchema = _resolver.GetSchema(resolvedId);
                if (resolvedSchema != null)
                {
                    // resolved schema is not null but referencing member allows nulls
                    // change resolved schema to allow nulls. hacky but what are ya gonna do?
                    if (valueRequired != Required.Always && !HasFlag(resolvedSchema.Type, JsonSchemaType.Null))
                    {
                        resolvedSchema.Type |= JsonSchemaType.Null;
                    }
                    if (required && resolvedSchema.Required != true)
                    {
                        resolvedSchema.Required = true;
                    }

                    return(resolvedSchema);
                }
            }

            // test for unresolved circular reference
            if (_stack.Any(tc => tc.Type == type))
            {
                throw new Exception("Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.".FormatWith(CultureInfo.InvariantCulture, type));
            }

            JsonContract  contract = ContractResolver.ResolveContract(type);
            JsonConverter converter;

            if ((converter = contract.Converter) != null || (converter = contract.InternalConverter) != null)
            {
                JsonSchema converterSchema = converter.GetSchema();
                if (converterSchema != null)
                {
                    return(converterSchema);
                }
            }

            Push(new TypeSchema(type, new JsonSchema()));

            if (explicitId != null)
            {
                CurrentSchema.Id = explicitId;
            }

            if (required)
            {
                CurrentSchema.Required = true;
            }
            CurrentSchema.Title       = GetTitle(type);
            CurrentSchema.Description = GetDescription(type);

            if (converter != null)
            {
                // todo: Add GetSchema to JsonConverter and use here?
                CurrentSchema.Type = JsonSchemaType.Any;
            }
            else if (contract is JsonDictionaryContract)
            {
                CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);

                Type keyType;
                Type valueType;
                ReflectionUtils.GetDictionaryKeyValueTypes(type, out keyType, out valueType);

                if (keyType != null)
                {
                    // can be converted to a string
                    if (typeof(IConvertible).IsAssignableFrom(keyType))
                    {
                        CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
                    }
                }
            }
            else if (contract is JsonArrayContract)
            {
                CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired);

                CurrentSchema.Id = GetTypeId(type, false);

                JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
                bool allowNullItem = (arrayAttribute != null) ? arrayAttribute.AllowNullItems : true;

                Type collectionItemType = ReflectionUtils.GetCollectionItemType(type);
                if (collectionItemType != null)
                {
                    CurrentSchema.Items = new List <JsonSchema>();
                    CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, false));
                }
            }
            else if (contract is JsonPrimitiveContract)
            {
                CurrentSchema.Type = GetJsonSchemaType(type, valueRequired);

                if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum && !type.IsDefined(typeof(FlagsAttribute), true))
                {
                    CurrentSchema.Enum    = new List <JToken>();
                    CurrentSchema.Options = new Dictionary <JToken, string>();

                    EnumValues <long> enumValues = EnumUtils.GetNamesAndValues <long>(type);
                    foreach (EnumValue <long> enumValue in enumValues)
                    {
                        JToken value = JToken.FromObject(enumValue.Value);

                        CurrentSchema.Enum.Add(value);
                        CurrentSchema.Options.Add(value, enumValue.Name);
                    }
                }
            }
            else if (contract is JsonObjectContract)
            {
                CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
                CurrentSchema.Id   = GetTypeId(type, false);
                GenerateObjectSchema(type, (JsonObjectContract)contract);
            }
#if !SILVERLIGHT && !PocketPC
            else if (contract is JsonISerializableContract)
            {
                CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
                CurrentSchema.Id   = GetTypeId(type, false);
                GenerateISerializableContract(type, (JsonISerializableContract)contract);
            }
#endif
            else if (contract is JsonStringContract)
            {
                JsonSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                                      ? JsonSchemaType.String
                                      : AddNullType(JsonSchemaType.String, valueRequired);

                CurrentSchema.Type = schemaType;
            }
            else if (contract is JsonLinqContract)
            {
                CurrentSchema.Type = JsonSchemaType.Any;
            }
            else
            {
                throw new Exception("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
            }

            return(Pop().Schema);
        }