You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
10 KiB

  1. #region License
  2. // Copyright (c) 2007 James Newton-King
  3. //
  4. // Permission is hereby granted, free of charge, to any person
  5. // obtaining a copy of this software and associated documentation
  6. // files (the "Software"), to deal in the Software without
  7. // restriction, including without limitation the rights to use,
  8. // copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the
  10. // Software is furnished to do so, subject to the following
  11. // conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  18. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  23. // OTHER DEALINGS IN THE SOFTWARE.
  24. #endregion
  25. using System;
  26. using System.Collections.Generic;
  27. using Newtonsoft.Json.Linq;
  28. using Newtonsoft.Json.Serialization;
  29. using Newtonsoft.Json.Utilities;
  30. #if NET20
  31. using Newtonsoft.Json.Utilities.LinqBridge;
  32. #else
  33. using System.Linq;
  34. #endif
  35. namespace Newtonsoft.Json.Schema
  36. {
  37. [Obsolete("JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.")]
  38. internal class JsonSchemaWriter
  39. {
  40. private readonly JsonWriter _writer;
  41. private readonly JsonSchemaResolver _resolver;
  42. public JsonSchemaWriter(JsonWriter writer, JsonSchemaResolver resolver)
  43. {
  44. ValidationUtils.ArgumentNotNull(writer, nameof(writer));
  45. _writer = writer;
  46. _resolver = resolver;
  47. }
  48. private void ReferenceOrWriteSchema(JsonSchema schema)
  49. {
  50. if (schema.Id != null && _resolver.GetSchema(schema.Id) != null)
  51. {
  52. _writer.WriteStartObject();
  53. _writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
  54. _writer.WriteValue(schema.Id);
  55. _writer.WriteEndObject();
  56. }
  57. else
  58. {
  59. WriteSchema(schema);
  60. }
  61. }
  62. public void WriteSchema(JsonSchema schema)
  63. {
  64. ValidationUtils.ArgumentNotNull(schema, nameof(schema));
  65. if (!_resolver.LoadedSchemas.Contains(schema))
  66. {
  67. _resolver.LoadedSchemas.Add(schema);
  68. }
  69. _writer.WriteStartObject();
  70. WritePropertyIfNotNull(_writer, JsonSchemaConstants.IdPropertyName, schema.Id);
  71. WritePropertyIfNotNull(_writer, JsonSchemaConstants.TitlePropertyName, schema.Title);
  72. WritePropertyIfNotNull(_writer, JsonSchemaConstants.DescriptionPropertyName, schema.Description);
  73. WritePropertyIfNotNull(_writer, JsonSchemaConstants.RequiredPropertyName, schema.Required);
  74. WritePropertyIfNotNull(_writer, JsonSchemaConstants.ReadOnlyPropertyName, schema.ReadOnly);
  75. WritePropertyIfNotNull(_writer, JsonSchemaConstants.HiddenPropertyName, schema.Hidden);
  76. WritePropertyIfNotNull(_writer, JsonSchemaConstants.TransientPropertyName, schema.Transient);
  77. if (schema.Type != null)
  78. {
  79. WriteType(JsonSchemaConstants.TypePropertyName, _writer, schema.Type.GetValueOrDefault());
  80. }
  81. if (!schema.AllowAdditionalProperties)
  82. {
  83. _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName);
  84. _writer.WriteValue(schema.AllowAdditionalProperties);
  85. }
  86. else
  87. {
  88. if (schema.AdditionalProperties != null)
  89. {
  90. _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName);
  91. ReferenceOrWriteSchema(schema.AdditionalProperties);
  92. }
  93. }
  94. if (!schema.AllowAdditionalItems)
  95. {
  96. _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName);
  97. _writer.WriteValue(schema.AllowAdditionalItems);
  98. }
  99. else
  100. {
  101. if (schema.AdditionalItems != null)
  102. {
  103. _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName);
  104. ReferenceOrWriteSchema(schema.AdditionalItems);
  105. }
  106. }
  107. WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PropertiesPropertyName, schema.Properties);
  108. WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PatternPropertiesPropertyName, schema.PatternProperties);
  109. WriteItems(schema);
  110. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumPropertyName, schema.Minimum);
  111. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumPropertyName, schema.Maximum);
  112. WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMinimumPropertyName, schema.ExclusiveMinimum);
  113. WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMaximumPropertyName, schema.ExclusiveMaximum);
  114. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumLengthPropertyName, schema.MinimumLength);
  115. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumLengthPropertyName, schema.MaximumLength);
  116. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumItemsPropertyName, schema.MinimumItems);
  117. WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumItemsPropertyName, schema.MaximumItems);
  118. WritePropertyIfNotNull(_writer, JsonSchemaConstants.DivisibleByPropertyName, schema.DivisibleBy);
  119. WritePropertyIfNotNull(_writer, JsonSchemaConstants.FormatPropertyName, schema.Format);
  120. WritePropertyIfNotNull(_writer, JsonSchemaConstants.PatternPropertyName, schema.Pattern);
  121. if (schema.Enum != null)
  122. {
  123. _writer.WritePropertyName(JsonSchemaConstants.EnumPropertyName);
  124. _writer.WriteStartArray();
  125. foreach (JToken token in schema.Enum)
  126. {
  127. token.WriteTo(_writer);
  128. }
  129. _writer.WriteEndArray();
  130. }
  131. if (schema.Default != null)
  132. {
  133. _writer.WritePropertyName(JsonSchemaConstants.DefaultPropertyName);
  134. schema.Default.WriteTo(_writer);
  135. }
  136. if (schema.Disallow != null)
  137. {
  138. WriteType(JsonSchemaConstants.DisallowPropertyName, _writer, schema.Disallow.GetValueOrDefault());
  139. }
  140. if (schema.Extends != null && schema.Extends.Count > 0)
  141. {
  142. _writer.WritePropertyName(JsonSchemaConstants.ExtendsPropertyName);
  143. if (schema.Extends.Count == 1)
  144. {
  145. ReferenceOrWriteSchema(schema.Extends[0]);
  146. }
  147. else
  148. {
  149. _writer.WriteStartArray();
  150. foreach (JsonSchema jsonSchema in schema.Extends)
  151. {
  152. ReferenceOrWriteSchema(jsonSchema);
  153. }
  154. _writer.WriteEndArray();
  155. }
  156. }
  157. _writer.WriteEndObject();
  158. }
  159. private void WriteSchemaDictionaryIfNotNull(JsonWriter writer, string propertyName, IDictionary<string, JsonSchema> properties)
  160. {
  161. if (properties != null)
  162. {
  163. writer.WritePropertyName(propertyName);
  164. writer.WriteStartObject();
  165. foreach (KeyValuePair<string, JsonSchema> property in properties)
  166. {
  167. writer.WritePropertyName(property.Key);
  168. ReferenceOrWriteSchema(property.Value);
  169. }
  170. writer.WriteEndObject();
  171. }
  172. }
  173. private void WriteItems(JsonSchema schema)
  174. {
  175. if (schema.Items == null && !schema.PositionalItemsValidation)
  176. {
  177. return;
  178. }
  179. _writer.WritePropertyName(JsonSchemaConstants.ItemsPropertyName);
  180. if (!schema.PositionalItemsValidation)
  181. {
  182. if (schema.Items != null && schema.Items.Count > 0)
  183. {
  184. ReferenceOrWriteSchema(schema.Items[0]);
  185. }
  186. else
  187. {
  188. _writer.WriteStartObject();
  189. _writer.WriteEndObject();
  190. }
  191. return;
  192. }
  193. _writer.WriteStartArray();
  194. if (schema.Items != null)
  195. {
  196. foreach (JsonSchema itemSchema in schema.Items)
  197. {
  198. ReferenceOrWriteSchema(itemSchema);
  199. }
  200. }
  201. _writer.WriteEndArray();
  202. }
  203. private void WriteType(string propertyName, JsonWriter writer, JsonSchemaType type)
  204. {
  205. if (Enum.IsDefined(typeof(JsonSchemaType), type))
  206. {
  207. writer.WritePropertyName(propertyName);
  208. writer.WriteValue(JsonSchemaBuilder.MapType(type));
  209. }
  210. else
  211. {
  212. IEnumerator<JsonSchemaType> en = EnumUtils.GetFlagsValues(type).Where(v => v != JsonSchemaType.None).GetEnumerator();
  213. if (en.MoveNext())
  214. {
  215. writer.WritePropertyName(propertyName);
  216. JsonSchemaType first = en.Current;
  217. if (en.MoveNext())
  218. {
  219. writer.WriteStartArray();
  220. writer.WriteValue(JsonSchemaBuilder.MapType(first));
  221. do
  222. {
  223. writer.WriteValue(JsonSchemaBuilder.MapType(en.Current));
  224. } while (en.MoveNext());
  225. writer.WriteEndArray();
  226. }
  227. else
  228. {
  229. writer.WriteValue(JsonSchemaBuilder.MapType(first));
  230. }
  231. }
  232. }
  233. }
  234. private void WritePropertyIfNotNull(JsonWriter writer, string propertyName, object value)
  235. {
  236. if (value != null)
  237. {
  238. writer.WritePropertyName(propertyName);
  239. writer.WriteValue(value);
  240. }
  241. }
  242. }
  243. }