简体   繁体   中英

how to make the json schema flexible enough to handle case sensitive input for enum?

Please refer to this question for the introduction Two way binding dependences based on enum value in json schema .

Now the case is that if I pass userType = CUSTOMER then it doesn't accept the request and in also the case of userType = customer .

Can anyone suggest me JSON schema solution for this?

There isn't a way to do this that isn't awful, but the least awful thing I can think of is to use pattern with a regex that includes both cases.

{
  "type": "string",
  "anyOf": [
    { "title": "Customer", "pattern": "[Cc][Uu][Ss][Tt][Oo][Mm][Ee][Rr]" },
    { "title": "Admin", "pattern": "[Aa][Dd][Mm][Ii][Nn]" },
  ]
}

(The title isn't necessary, it's just a nicety for the poor dev who has to read this schema)

This was the exact use case I was trying to solve from the last couple of days, One thing that is clear is schema does not support it directly.

Now if you are using some kind of third-party schema validator tool, they might give you some interface to write you own customize validator ( https://github.com/everit-org/json-schema )

There is another way that we can do is preprocess the data before validating it. Let's say in your case userType is the value that is case insensitive and is a set of values only (Customer, customer, CUSTOMER). So I would suggest keeping the enum value as customer [lowercase] and before your JSON is going to schema validator preprocess it to put all the values in the specific key as lowercase value.

The code to preprocess your JSON might look as to below-

CONVERT_TO_LOWER_CASE_KEY_SET - Set of keys that are case insensitive while validation.

private JsonObject preProcessInputJsonObject(JsonObject inputJsonBody) {
   inputJsonBody.forEach(innerObject -> {
        if (innerObject.getValue() instanceof String) {
            String value = (String) innerObject.getValue();
            if (value.trim().isEmpty())
                inputJsonBody.putNull(innerObject.getKey());
            else if (CONVERT_TO_LOWER_CASE_KEY_SET.contains(innerObject.getKey()))
                inputJsonBody.put(innerObject.getKey(), value.trim().toLowerCase());
            else
                inputJsonBody.put(innerObject.getKey(), value.trim());
        }
        if (innerObject.getValue() instanceof JsonObject)
            inputJsonBody.put(innerObject.getKey(), preProcessInputJsonObject((JsonObject) innerObject.getValue()));
        if (innerObject.getValue() instanceof JsonArray)
            inputJsonBody.put(innerObject.getKey(), preProcessJsonArray((JsonArray) innerObject.getValue()));
    });
    return inputJsonBody;
}

private JsonArray preProcessJsonArray(JsonArray inputJsonArray) {
    List jsonArrayList = inputJsonArray.copy().getList();
    final int size = jsonArrayList.size();
    for (int iterator = 0; iterator < size; iterator++) {
        if (jsonArrayList.get(iterator) instanceof String) {
            String val = (String) jsonArrayList.get(iterator);
            if (val.trim().isEmpty())
                jsonArrayList.set(iterator, null);
            else
                jsonArrayList.set(iterator, val.trim());
        }
        if (jsonArrayList.get(iterator) instanceof JsonObject)
            jsonArrayList.set(iterator, preProcessInputJsonObject((JsonObject) jsonArrayList.get(iterator)));
        if (jsonArrayList.get(iterator) instanceof JsonArray)
            jsonArrayList.set(iterator, preProcessJsonArray((JsonArray) jsonArrayList.get(iterator)));
    }
    return new JsonArray(jsonArrayList);
}

Note: I also tried removing extra spaces in the string before validating it.

Hope its helpful, let me know if you see any concern in it.

One final thing my preprocess data code in java hopefully, you can write something similar in js as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM