FEATURE REQUEST: option to ignore unrecognized attributes when creating a typed document from a JSON string #11
-
Suppose we have registered a {
"uuid": "{\"type\":\"string\"}",
"name": {
"given": "{\"type\":\"string\"}",
"family": "{\"type\":\"string\"}"
}
} Then we can easily parse a JSON string such as: {
"uuid": "404b9ff1-fb45-4276-9665-e6f87f725a9e",
"name": {
"given": "John",
"family": "Doe"
}
} or (omitting some attributes this time): {
"name": {
"given": "Jane"
}
} into a typed Document person = new JDocument("person", json);
System.out.println(person.getType()); // yields "person" However if the input JSON includes some extra attributes, say: {
"uuid": "404b9ff1-fb45-4276-9665-e6f87f725a9e",
"dob": "1999-12-31", // <~ not defined in type spec
"name": {
"given": "John",
"family": "Doe"
}
} then the In the spirit of Postel's Law - "be liberal in what you accept and conservative in what you send" - it would sometimes be helpful to simply ignore the unrecognized attributes and extract the otherwise valid One way to achieve this behavior is to first parse the input JSON as an untyped but for sake of discussion here's a utility method that implements that strategy: /**
* Create a valid, typed JDocument from a JSON string, ignoring any attributes
* not defined in the specified model (but validating the recognized attributes
* as we otherwise would).
*
* @param type name of the (previously loaded) document model to apply
* @param json the stringified JSON data to be parsed
*
* @return a JDocument with of specified type that only contains the attributes
* defined in the model
*
* @throws UnifyException when the named type definition cannot be found, the input
* json is not well-formed, or the resulting JDocument is
* otherwise invalid even after any unrecognized attributes
* are removed
*/
JDocument parseTypedJsonIgnoringUnrecognizedAttributes(final String type, final String json) throws UnifyException {
// Grab the specified model definition...
final Document model = JDocument.getDocumentModel(type);
if (model == null) { // ...aborting with an exception if not found.
throw new UnifyException("jdoc_err_29", type);
} else {
// Otherwise parse the input json as an untyped document...
final JDocument doc = new JDocument(json);
// ...and strip out any attributes that aren't defined in the model.
for (String path : doc.flatten()) {
// (note that arrays in the model will only contain a single element, so we must
// change any array index references found in the untyped document path to index
// 0 to create the corresponding path in the model document)
final String modelPath = path.replaceAll("\\[\\d+\\]", "[0]");
if (!model.pathExists(modelPath)) {
doc.deletePath(path);
}
}
// Now we can assign the type and validate as we usually would.
doc.setType(type);
doc.validate(type); // <~~ I'm not sure if this call is strictly necessary
return doc;
}
} There may be a more elegant or efficient way to go about this - and I think it might be more appropriate to expose this as an optional If this is a feature you'd be interested in I'm happy to submit a full PR for it, but I thought it best to open it up for discussion/guidance/feedback first. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 2 replies
-
Hi, Thanks for taking out the time to write out the problem you are facing and also proposing a solution for the same. I really do appreciate the fact that you took time to write out the problem and solution in detail and very clearly too. I wanted to give you the good news that we internally faced this very problem here in Amex in the project that we developed JDocs for and had already solved this a couple of years back. You will find the reference to it in the documentation on the main page itself (https://github.com/americanexpress/unify-jdocs), though I have to admit it is a bit buried and not very self-evident. Please search for the heading "Validating typed documents" to know the usage. I am reproducing the contents from the documentation below. You can have what you are looking for at per document level or at JDocs level. I hope this helps you. Happy to help if you have any further questions. Thanks and regards. By default, typed documents are validated when they are created and when any read / write operation is performed on them. However there may be cases, when we do not want to validate the document at the time of creation but only at the time of reading and writing. This is a typical scenario in the use of APIs which can return extra blocks and paths which may not be present in the model document and which we may not be interested in. If we were to validate at the time of creating the document, the model validations would fail unless we kept the model document in sync with all the changes happening on the API side. Most of the times this is not possible as the teams are separate and there is no reason that adding fields to the response which we are not interested in should cause a failure. To take care of this scenario, we have two alternatives: Use the overloaded JDocument constructor to specify that the validation should only be done while reading / writing paths. This way the default behaviour will not change but can be set at a per document level public JDocument(String type,String json,boolean validateAtReadWriteOnly); |
Beta Was this translation helpful? Give feedback.
-
I'm not sure if that's solving the same problem (or if it is it's not clear to me how). My use case is something like this:
Essentially this is same function as the As I understand it, setting A. won't the unrecognzied attributes still trigger a validation error when I ultimately do the validation? I don't understand how to achieve the 2.i and 2.ii objectives above using |
Beta Was this translation helpful? Give feedback.
-
I see your point and agree - there needs to be a way to validate the document upfront (minus the fields not in the model) - I am just thinking of the most efficient and intuitive way to do this - give me a couple of days to think through and I will let you know - will implement in a week at max - hope that helps. BTW will update the documentation as well to make it more explicit - thanks! |
Beta Was this translation helpful? Give feedback.
-
Hi - have released 1.6.0. Please go through the release notes / documentation and let me know if you have any questions. Thanks. |
Beta Was this translation helpful? Give feedback.
Hi - have released 1.6.0. Please go through the release notes / documentation and let me know if you have any questions. Thanks.