-
Notifications
You must be signed in to change notification settings - Fork 497
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
433 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
276 changes: 276 additions & 0 deletions
276
core/src/main/java/com/alibaba/fastjson2/JSONSchema.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,276 @@ | ||
package com.alibaba.fastjson2; | ||
|
||
import org.everit.json.schema.StringSchema; | ||
|
||
import java.math.BigInteger; | ||
import java.util.*; | ||
|
||
public abstract class JSONSchema { | ||
final String title; | ||
final String description; | ||
|
||
JSONSchema(JSONObject input) { | ||
this.title = input.getString("title"); | ||
this.description = input.getString("description"); | ||
} | ||
|
||
public static JSONSchema of(JSONObject input) { | ||
return new ObjectSchema(input); | ||
} | ||
|
||
public String getTitle() { | ||
return title; | ||
} | ||
|
||
public String getDescription() { | ||
return description; | ||
} | ||
|
||
public abstract Type getType(); | ||
|
||
public abstract void validate(Object value); | ||
|
||
public enum Type { | ||
Null, | ||
Boolean, | ||
Object, | ||
Array, | ||
Number, | ||
String, | ||
|
||
// extended type | ||
Integer, | ||
} | ||
|
||
public static final class StringSchema extends JSONSchema { | ||
StringSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.String; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
if (value == null) { | ||
return; | ||
} | ||
|
||
if (value instanceof String) { | ||
return; | ||
} | ||
|
||
throw new JSONValidException("type Integer not match : " + value.getClass().getName()); | ||
} | ||
} | ||
|
||
public static final class IntegerSchema extends JSONSchema { | ||
IntegerSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Integer; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
if (value == null) { | ||
return; | ||
} | ||
|
||
Class valueClass = value.getClass(); | ||
if (valueClass == Byte.class | ||
|| valueClass == Short.class | ||
|| valueClass == Integer.class | ||
|| valueClass == Long.class | ||
|| valueClass == BigInteger.class | ||
) { | ||
return; | ||
} | ||
|
||
throw new JSONValidException("type Integer not match : " + valueClass.getName()); | ||
} | ||
} | ||
|
||
public static final class NumberSchema extends JSONSchema { | ||
NumberSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Number; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
if (value == null) { | ||
return; | ||
} | ||
|
||
if (value instanceof Number) { | ||
return; | ||
} | ||
|
||
throw new JSONValidException("type Integer not match : " + value.getClass().getName()); | ||
} | ||
} | ||
|
||
public static final class BooleanSchemaSchema extends JSONSchema { | ||
BooleanSchemaSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Boolean; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
} | ||
|
||
public static final class NullSchemaSchema extends JSONSchema { | ||
NullSchemaSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Null; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
} | ||
|
||
public static final class ArraySchemaSchema extends JSONSchema { | ||
ArraySchemaSchema(JSONObject input) { | ||
super(input); | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Array; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
} | ||
|
||
public static final class ObjectSchema extends JSONSchema { | ||
final JSONObject properties; | ||
final Set<String> required; | ||
|
||
public ObjectSchema(JSONObject input) { | ||
super(input); | ||
this.properties = new JSONObject(); | ||
|
||
JSONObject properties = input.getJSONObject("properties"); | ||
if (properties != null) { | ||
for (Iterator<Map.Entry<String, Object>> it = properties.entrySet().iterator(); it.hasNext();) { | ||
Map.Entry<String, Object> entry = it.next(); | ||
String entryKey = entry.getKey(); | ||
JSONObject entryValue = (JSONObject) entry.getValue(); | ||
Type type = entryValue.getObject("type", Type.class); | ||
if (type == null) { | ||
throw new JSONException("type required"); | ||
} | ||
|
||
JSONSchema schema; | ||
switch (type) { | ||
case String: | ||
schema = new StringSchema(entryValue); | ||
break; | ||
case Integer: | ||
schema = new IntegerSchema(entryValue); | ||
break; | ||
case Number: | ||
schema = new NumberSchema(entryValue); | ||
break; | ||
case Null: | ||
schema = new NullSchemaSchema(entryValue); | ||
break; | ||
case Boolean: | ||
schema = new BooleanSchemaSchema(entryValue); | ||
break; | ||
case Object: | ||
schema = new ObjectSchema(entryValue); | ||
break; | ||
case Array: | ||
schema = new ArraySchemaSchema(entryValue); | ||
break; | ||
default: | ||
throw new JSONException("not support type : " + type); | ||
} | ||
|
||
this.properties.put(entryKey, schema); | ||
} | ||
} | ||
|
||
JSONArray required = input.getJSONArray("required"); | ||
if (required == null) { | ||
this.required = Collections.emptySet(); | ||
} else { | ||
this.required = new LinkedHashSet<>(required.size()); | ||
for (int i = 0; i < required.size(); i++) { | ||
this.required.add( | ||
required.getString(i) | ||
); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.Object; | ||
} | ||
|
||
@Override | ||
public void validate(Object value) { | ||
if (value instanceof Map) { | ||
Map map = (Map) value; | ||
|
||
for (String item : required) { | ||
if (!map.containsKey(item)) { | ||
throw new JSONValidException("require property '" + item + "'"); | ||
} | ||
} | ||
|
||
for (Map.Entry<String, Object> entry : properties.entrySet()) { | ||
String key = entry.getKey(); | ||
JSONSchema schema = (JSONSchema) entry.getValue(); | ||
|
||
Object propertyValue = map.get(key); | ||
schema.validate(propertyValue); | ||
} | ||
|
||
return; | ||
} | ||
|
||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
public Map<String, JSONSchema> getProperties() { | ||
return properties; | ||
} | ||
|
||
public JSONSchema getProperty(String key) { | ||
return (JSONSchema) properties.get(key); | ||
} | ||
|
||
public Set<String> getRequired() { | ||
return required; | ||
} | ||
} | ||
} |
Oops, something went wrong.