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 
26 using System;
27 using System.Collections.Generic;
28 using System.IO;
29 using Newtonsoft.Json.Linq;
30 using Newtonsoft.Json.Utilities;
31 using System.Globalization;
32 
33 namespace Newtonsoft.Json.Schema
34 {
35     /// <summary>
36     /// <para>
37     /// An in-memory representation of a JSON Schema.
38     /// </para>
39     /// <note type="caution">
40     /// JSON Schema validation has been moved to its own package. See <see href="http://www.newtonsoft.com/jsonschema">http://www.newtonsoft.com/jsonschema</see> for more details.
41     /// </note>
42     /// </summary>
43     [Obsolete("JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.")]
44     public class JsonSchema
45     {
46         /// <summary>
47         /// Gets or sets the id.
48         /// </summary>
49         public string Id { get; set; }
50 
51         /// <summary>
52         /// Gets or sets the title.
53         /// </summary>
54         public string Title { get; set; }
55 
56         /// <summary>
57         /// Gets or sets whether the object is required.
58         /// </summary>
59         public bool? Required { get; set; }
60 
61         /// <summary>
62         /// Gets or sets whether the object is read only.
63         /// </summary>
64         public bool? ReadOnly { get; set; }
65 
66         /// <summary>
67         /// Gets or sets whether the object is visible to users.
68         /// </summary>
69         public bool? Hidden { get; set; }
70 
71         /// <summary>
72         /// Gets or sets whether the object is transient.
73         /// </summary>
74         public bool? Transient { get; set; }
75 
76         /// <summary>
77         /// Gets or sets the description of the object.
78         /// </summary>
79         public string Description { get; set; }
80 
81         /// <summary>
82         /// Gets or sets the types of values allowed by the object.
83         /// </summary>
84         /// <value>The type.</value>
85         public JsonSchemaType? Type { get; set; }
86 
87         /// <summary>
88         /// Gets or sets the pattern.
89         /// </summary>
90         /// <value>The pattern.</value>
91         public string Pattern { get; set; }
92 
93         /// <summary>
94         /// Gets or sets the minimum length.
95         /// </summary>
96         /// <value>The minimum length.</value>
97         public int? MinimumLength { get; set; }
98 
99         /// <summary>
100         /// Gets or sets the maximum length.
101         /// </summary>
102         /// <value>The maximum length.</value>
103         public int? MaximumLength { get; set; }
104 
105         /// <summary>
106         /// Gets or sets a number that the value should be divisble by.
107         /// </summary>
108         /// <value>A number that the value should be divisble by.</value>
109         public double? DivisibleBy { get; set; }
110 
111         /// <summary>
112         /// Gets or sets the minimum.
113         /// </summary>
114         /// <value>The minimum.</value>
115         public double? Minimum { get; set; }
116 
117         /// <summary>
118         /// Gets or sets the maximum.
119         /// </summary>
120         /// <value>The maximum.</value>
121         public double? Maximum { get; set; }
122 
123         /// <summary>
124         /// Gets or sets a flag indicating whether the value can not equal the number defined by the "minimum" attribute.
125         /// </summary>
126         /// <value>A flag indicating whether the value can not equal the number defined by the "minimum" attribute.</value>
127         public bool? ExclusiveMinimum { get; set; }
128 
129         /// <summary>
130         /// Gets or sets a flag indicating whether the value can not equal the number defined by the "maximum" attribute.
131         /// </summary>
132         /// <value>A flag indicating whether the value can not equal the number defined by the "maximum" attribute.</value>
133         public bool? ExclusiveMaximum { get; set; }
134 
135         /// <summary>
136         /// Gets or sets the minimum number of items.
137         /// </summary>
138         /// <value>The minimum number of items.</value>
139         public int? MinimumItems { get; set; }
140 
141         /// <summary>
142         /// Gets or sets the maximum number of items.
143         /// </summary>
144         /// <value>The maximum number of items.</value>
145         public int? MaximumItems { get; set; }
146 
147         /// <summary>
148         /// Gets or sets the <see cref="JsonSchema"/> of items.
149         /// </summary>
150         /// <value>The <see cref="JsonSchema"/> of items.</value>
151         public IList<JsonSchema> Items { get; set; }
152 
153         /// <summary>
154         /// Gets or sets a value indicating whether items in an array are validated using the <see cref="JsonSchema"/> instance at their array position from <see cref="JsonSchema.Items"/>.
155         /// </summary>
156         /// <value>
157         /// 	<c>true</c> if items are validated using their array position; otherwise, <c>false</c>.
158         /// </value>
159         public bool PositionalItemsValidation { get; set; }
160 
161         /// <summary>
162         /// Gets or sets the <see cref="JsonSchema"/> of additional items.
163         /// </summary>
164         /// <value>The <see cref="JsonSchema"/> of additional items.</value>
165         public JsonSchema AdditionalItems { get; set; }
166 
167         /// <summary>
168         /// Gets or sets a value indicating whether additional items are allowed.
169         /// </summary>
170         /// <value>
171         /// 	<c>true</c> if additional items are allowed; otherwise, <c>false</c>.
172         /// </value>
173         public bool AllowAdditionalItems { get; set; }
174 
175         /// <summary>
176         /// Gets or sets whether the array items must be unique.
177         /// </summary>
178         public bool UniqueItems { get; set; }
179 
180         /// <summary>
181         /// Gets or sets the <see cref="JsonSchema"/> of properties.
182         /// </summary>
183         /// <value>The <see cref="JsonSchema"/> of properties.</value>
184         public IDictionary<string, JsonSchema> Properties { get; set; }
185 
186         /// <summary>
187         /// Gets or sets the <see cref="JsonSchema"/> of additional properties.
188         /// </summary>
189         /// <value>The <see cref="JsonSchema"/> of additional properties.</value>
190         public JsonSchema AdditionalProperties { get; set; }
191 
192         /// <summary>
193         /// Gets or sets the pattern properties.
194         /// </summary>
195         /// <value>The pattern properties.</value>
196         public IDictionary<string, JsonSchema> PatternProperties { get; set; }
197 
198         /// <summary>
199         /// Gets or sets a value indicating whether additional properties are allowed.
200         /// </summary>
201         /// <value>
202         /// 	<c>true</c> if additional properties are allowed; otherwise, <c>false</c>.
203         /// </value>
204         public bool AllowAdditionalProperties { get; set; }
205 
206         /// <summary>
207         /// Gets or sets the required property if this property is present.
208         /// </summary>
209         /// <value>The required property if this property is present.</value>
210         public string Requires { get; set; }
211 
212         /// <summary>
213         /// Gets or sets the a collection of valid enum values allowed.
214         /// </summary>
215         /// <value>A collection of valid enum values allowed.</value>
216         public IList<JToken> Enum { get; set; }
217 
218         /// <summary>
219         /// Gets or sets disallowed types.
220         /// </summary>
221         /// <value>The disallow types.</value>
222         public JsonSchemaType? Disallow { get; set; }
223 
224         /// <summary>
225         /// Gets or sets the default value.
226         /// </summary>
227         /// <value>The default value.</value>
228         public JToken Default { get; set; }
229 
230         /// <summary>
231         /// Gets or sets the collection of <see cref="JsonSchema"/> that this schema extends.
232         /// </summary>
233         /// <value>The collection of <see cref="JsonSchema"/> that this schema extends.</value>
234         public IList<JsonSchema> Extends { get; set; }
235 
236         /// <summary>
237         /// Gets or sets the format.
238         /// </summary>
239         /// <value>The format.</value>
240         public string Format { get; set; }
241 
242         internal string Location { get; set; }
243 
244         private readonly string _internalId = Guid.NewGuid().ToString("N");
245 
246         internal string InternalId
247         {
248             get { return _internalId; }
249         }
250 
251         // if this is set then this schema instance is just a deferred reference
252         // and will be replaced when the schema reference is resolved
253         internal string DeferredReference { get; set; }
254         internal bool ReferencesResolved { get; set; }
255 
256         /// <summary>
257         /// Initializes a new instance of the <see cref="JsonSchema"/> class.
258         /// </summary>
JsonSchema()259         public JsonSchema()
260         {
261             AllowAdditionalProperties = true;
262             AllowAdditionalItems = true;
263         }
264 
265         /// <summary>
266         /// Reads a <see cref="JsonSchema"/> from the specified <see cref="JsonReader"/>.
267         /// </summary>
268         /// <param name="reader">The <see cref="JsonReader"/> containing the JSON Schema to read.</param>
269         /// <returns>The <see cref="JsonSchema"/> object representing the JSON Schema.</returns>
Read(JsonReader reader)270         public static JsonSchema Read(JsonReader reader)
271         {
272             return Read(reader, new JsonSchemaResolver());
273         }
274 
275         /// <summary>
276         /// Reads a <see cref="JsonSchema"/> from the specified <see cref="JsonReader"/>.
277         /// </summary>
278         /// <param name="reader">The <see cref="JsonReader"/> containing the JSON Schema to read.</param>
279         /// <param name="resolver">The <see cref="JsonSchemaResolver"/> to use when resolving schema references.</param>
280         /// <returns>The <see cref="JsonSchema"/> object representing the JSON Schema.</returns>
Read(JsonReader reader, JsonSchemaResolver resolver)281         public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver)
282         {
283             ValidationUtils.ArgumentNotNull(reader, nameof(reader));
284             ValidationUtils.ArgumentNotNull(resolver, nameof(resolver));
285 
286             JsonSchemaBuilder builder = new JsonSchemaBuilder(resolver);
287             return builder.Read(reader);
288         }
289 
290         /// <summary>
291         /// Load a <see cref="JsonSchema"/> from a string that contains schema JSON.
292         /// </summary>
293         /// <param name="json">A <see cref="String"/> that contains JSON.</param>
294         /// <returns>A <see cref="JsonSchema"/> populated from the string that contains JSON.</returns>
Parse(string json)295         public static JsonSchema Parse(string json)
296         {
297             return Parse(json, new JsonSchemaResolver());
298         }
299 
300         /// <summary>
301         /// Parses the specified json.
302         /// </summary>
303         /// <param name="json">The json.</param>
304         /// <param name="resolver">The resolver.</param>
305         /// <returns>A <see cref="JsonSchema"/> populated from the string that contains JSON.</returns>
Parse(string json, JsonSchemaResolver resolver)306         public static JsonSchema Parse(string json, JsonSchemaResolver resolver)
307         {
308             ValidationUtils.ArgumentNotNull(json, nameof(json));
309 
310             using (JsonReader reader = new JsonTextReader(new StringReader(json)))
311             {
312                 return Read(reader, resolver);
313             }
314         }
315 
316         /// <summary>
317         /// Writes this schema to a <see cref="JsonWriter"/>.
318         /// </summary>
319         /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
WriteTo(JsonWriter writer)320         public void WriteTo(JsonWriter writer)
321         {
322             WriteTo(writer, new JsonSchemaResolver());
323         }
324 
325         /// <summary>
326         /// Writes this schema to a <see cref="JsonWriter"/> using the specified <see cref="JsonSchemaResolver"/>.
327         /// </summary>
328         /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
329         /// <param name="resolver">The resolver used.</param>
WriteTo(JsonWriter writer, JsonSchemaResolver resolver)330         public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver)
331         {
332             ValidationUtils.ArgumentNotNull(writer, nameof(writer));
333             ValidationUtils.ArgumentNotNull(resolver, nameof(resolver));
334 
335             JsonSchemaWriter schemaWriter = new JsonSchemaWriter(writer, resolver);
336             schemaWriter.WriteSchema(this);
337         }
338 
339         /// <summary>
340         /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
341         /// </summary>
342         /// <returns>
343         /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
344         /// </returns>
ToString()345         public override string ToString()
346         {
347             StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
348             JsonTextWriter jsonWriter = new JsonTextWriter(writer);
349             jsonWriter.Formatting = Formatting.Indented;
350 
351             WriteTo(jsonWriter);
352 
353             return writer.ToString();
354         }
355     }
356 }