Пример #1
0
        private JsonSchema BuildSchema()
        {
            if (_reader.TokenType != JsonToken.StartObject)
            {
                throw JsonReaderException.Create(_reader, "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 JsonReaderException.Create(_reader, "Found StartObject within the schema reference with the Id '{0}'".FormatWith(CultureInfo.InvariantCulture, id));
                    }
                }

                JsonSchema referencedSchema = _resolver.GetSchema(id);
                if (referencedSchema == null)
                {
                    throw new JsonException("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());
        }
Пример #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);
     }
 }
Пример #3
0
        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 JsonException("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
            {
                switch (contract.ContractType)
                {
                case JsonContractType.Object:
                    CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
                    CurrentSchema.Id   = GetTypeId(type, false);
                    GenerateObjectSchema(type, (JsonObjectContract)contract);
                    break;

                case JsonContractType.Array:
                    CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired);

                    CurrentSchema.Id = GetTypeId(type, false);

                    JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
                    bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);

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

                case JsonContractType.Primitive:
                    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);
                        }
                    }
                    break;

                case JsonContractType.String:
                    JsonSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
                                          ? JsonSchemaType.String
                                          : AddNullType(JsonSchemaType.String, valueRequired);

                    CurrentSchema.Type = schemaType;
                    break;

                case JsonContractType.Dictionary:
                    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 (ConvertUtils.IsConvertible(keyType))
                        {
                            CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
                        }
                    }
                    break;

#if !(SILVERLIGHT || NETFX_CORE || PORTABLE)
                case JsonContractType.Serializable:
                    CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
                    CurrentSchema.Id   = GetTypeId(type, false);
                    GenerateISerializableContract(type, (JsonISerializableContract)contract);
                    break;
#endif
#if !(NET35 || NET20 || WINDOWS_PHONE || PORTABLE)
                case JsonContractType.Dynamic:
#endif
                case JsonContractType.Linq:
                    CurrentSchema.Type = JsonSchemaType.Any;
                    break;

                default:
                    throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
                }
            }

            return(Pop().Schema);
        }