Is there an already established way of incorporating logic into a JSON Schema?
For example if I had a JSON of the following:
{
"Gross Pay": "100",
"Hours": "5",
"Rate": "20"
}
And I have a Schema requiring these 3 fields. If I wanted to ensure that the "Gross Pay" equals "Hours" x "Rate" where would be the best place to incorporate such logic?
No, you can't describe this type of assertions with JSON Schema. See validation keywords, there's nothing suitable there. There are some keywords like minimum or exclusiveMaximum, but they won't allow you to express Gross Pay = Hours * Rate.
Related
I´m getting a json from an application with a couple of nested subdocuments. Some of those documents are optional and not present all the time. I´m wondering if there is a best practice how to handel this.
e.g. (The document is just an example, the real one looks differnt but I can´t post it, the Example is copied from: How to represent sub-documents in JSON array as Java Collection using Jackson?): The Adreess subdocument is not present in every document I receive.
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jr44XEAR"
},
"Id": "00Qi000000Jr44XEAR",
"Name": "Kristen Akin",
"Address": {
"city": null,
"country": "USA",
"state": "CA",
"stateCode": null,
"street": null
},
"Phone": "(434) 369-3100"
}
Currently I´m receiving the data in the worst possible way I can imagine with a differnt type, which is like:
{
"attributes": {
"type": "Lead",
"url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jr44XEAR"
},
"Id": "00Qi000000Jr44XEAR",
"Name": "Kristen Akin",
"Address": "",
"Phone": "(434) 369-3100"
}
I want to suggest better ways and I´m wondering whats the best one?
Leaving the adress subdocument out completely
receiving "Adress: null"
receiving Adress: {}
receiving Adress: {"city": null, "country": null, ...}
anything else
Personally I would go with Nr. 3 because I still get a (sub)document and can treat it the usual way. Does anythin speak against it or are there any best practices for this situation?
Thanks in advance.
Best regards.
Go with 3.
Leaving the adress subdocument out completely
Would work for many deserialization tools, but it is hard to identify the structure and identify if something is missing on debugging easily
receiving "Adress: null"
Would work for many deserialization tools, but it is not a good practice to deliver null for more complex attributes like arrays or objects. You cannot identify, that this is a complex object easily.
receiving Adress: {}
It is a good practice to deliver empty arrays if they are empty and empty objects, if they are empty. You can identify that there could be a complex object but it is not available here. Please go with this solution
receiving Adress: {"city": null, "country": null, ...}
Don't do this. It gives you more details for the complex object, but you cannot identify easily if the address was not added on purpose or if the API partner sends incomplete address data by accident or if incomplete data is valid on their side.
I always differentiate between values which are:
set but empty: We usually interpret these values as valid values which are intended to be empty, like an empty address book, which may contain no entries at all.
undefined: usually this is an optional value. The application has to handle if it needs the data from somewhere else.
null: setting a value intentionally to null means to invalidate the value. We often use this to reset the data. In case of the address book means: there is no address book at all, even no empty one.
I would prefer these options:
1.: if it is left out, it is undefined and means that it is up to the application to handle undefined values. Especially for optional values, you should be aware of handling undefined values.
3.: if it is empty, you still have a valid address book, but an empty one, which makes the handling in code easier.
What I would avoid:
4.: You get an valid address with invalid data, so you have to deep-check if the address is usable, which increases the efforts on validation, so I would not use this option.
5.: changing the data type to "" is also bad because for typed languages it will make it hard to parse because it expects an object but receives a string.
We are currently using Pact-Broker in our Spring Boot application with really good results for our integration tests.
Our tests using Pact-Broker are base in a call to a REST API and comparing the response with the value in our provider, always using JSON format.
Our problem is that the values to compare are in a DB where the data is changing quite often, which make us update the tests really often.
Do you know if it is possible to just validate by the data type?
What we would like to try is to validate that the JSON is properly formed and the data type match, for example, if our REST API gives this output:
[
{
"action": "VIEW",
"id": 1,
"module": "A",
"section": "pendingList",
"state": null
},
{
"action": "VIEW",
"id": 2,
"module": "B",
"section": "finished",
"state": null
}
}
]
For example, what we would like to validate from the previous output is the following:
The JSON is well formed.
All the keys / value pair exists based in the model.
The value match a specific data type, for example, that the key action exist in all the entries and contains a string data type.
Do you know if this is possible to be accomplished with Pact-Broker? I was searching in the documentation but I did not found any example of how to do it.
Thanks a lot in advance.
Best regards.
Absolutely! The first 2 things Pact will always do without any extra work.
What you are talking about is referred to as flexible matching [1]. You don't want to match the value, but the type (or a regex). Given you are using Spring Boot, you may want to look at the various matchers available for Pact JVM [2].
I'm not sure if you meant it, but just for clarity, Pact and Pact Broker are separate things. Pact is the Open Source contract-testing framework, and Pact Broker [3] is a tool to help share and collaborate on those contracts with the team.
[1] https://docs.pact.io/getting_started/matching
[2] https://github.com/DiUS/pact-jvm/tree/master/consumer/pact-jvm-consumer#dsl-matching-methods
[3] https://github.com/pact-foundation/pact_broker/
Currently I'm working on a REST API with an object that has a status. Should I return the status as a string or as an object?
When is it smart to change from field being a primitive type to a field being an object?
[
{
"id": 1
"name": "Hello"
"status": "active"
},
{
"id": 1
"name": "Hello"
"status": {
"id": 0
"name": "active"
}
}
]
In terms of extensibility I would suggest going for and object.
Using an object also adds the advantage of being able to split responsibility in terms of identifying (via f.e. an id field) and describing (via f.e. a name or description field), in your case, a status.
Adding i18n as a possible necessity, an object would also have to carry a string as identifier.
All these things are not possible with simple primitives. Conclusion: go for an object.
Other interesting remarks are given here.
It depends on what you need to pass.
If you only want to distinguish between different states and have all other related information (strings, translations, images) on the client either way, you might only want to send a simple integer value and use an enum on the client side. This reduces the data to the smallest amount.
If you have data that changes within one status on the server side, you need an object to pass everything else.
But best practice here would be to reduce data as much as possible.
I need to transfer typed data structure into a server using JSON.
The original data is typed and I need the sever to reconstruct these typed data.
As a very simple example suppose I have the following data structure:
double pi1 = 3.14 (server must know is is double)
float pi2 = 3.14 (server must know is is float)
I understand the json is typeless.
I also searched and saw various implementations (ex: "__type" in asp net) and can invent one myself
ex.
{ "pi1": {"type": "double", "value": 3.14},
"pi2": {"type": "float", "value": 3.14} }
Is there any convention and/or efficient good practice for this or must I "invent" a type notation?
My application will be receiving a large json payload from an upstream system. This upsteam system is essentially a UI that will be collecting business requirements from a user, format those questions and facts into a json payload, and transmit the json to my application, which will validate it against a schema defined by the json-schema standard. The conundrum is that this upstream system is being built by a different team who doesn't necessarily understand all of the business requirements that need to be captured.
Take the following schema:
schema = {
"$schema": "http://json-schema.org/draft-04/schema#",
"title":"Requirements",
"description": "A Business Requirements Payload",
"type": "object",
"properties": {
"full_name": {
"type": "string"
},
"sex": {
"enum": ["m", "f"]
},
"age": {
"type": "number"
},
"consents": {
"type": "boolean"
}
},
"required": ["full_name", "sex", "age", "consents"],
"additionalProperties": False
}
Assume that the upstream system has no idea what a full_name, sex, or age was. Currently, I am having meetings explaining the nature of every field/question/fact that I require, default values that should show up on the UI, accompanying text labels that should show up to each field, and etc.
In brainstorming a mechanism to make this easier for everyone, I thought of tightly coupling the json-schema I am creating to the UI that the upstream system is building. What if I include these details inside of the json-schema itself, hand the json-schema to the upstream system, and let the UI team generate the UI with the accompanying text labels, default values, and etc?
For example, the full_name and sex fields could instead be described like this:
"full_name": {
"type": "string",
"default": "\"John Smith\"",
"label": "Full Name",
"text": "Please include your full name.",
"description": "This field will be the primary key in the database"
},
"sex": {
"enum": ["m", "f"],
"default": "m",
"enum_labels": ["Male", "Female"],
"label": "Sex",
"text": "Please include your sex.",
"description": "We want to run analytics on this field"
}
The UI team and I could come to an agreement on certain things:
If the field is of type string, generate a text box.
If the field is an enum, generate a combo box.
Use the field's label property infront of the form entry.
If the field is of type enum, generate pretty labels for the enum values by comparing positioninally against the enum_labels property.
Use the field's text property right below the form entry.
The Description field is only to help you, the UI guy, to know the business logic.
Here are some negatives to this approach:
Tightly coupling the view in this manner may not be optimal
If json-schema v5 introduces a keyword that I am using, such as text, the schema would break if I upgraded to v5 and then I would have to change the contract with the UI team. (What could also be done to avoid this is to use the description field to hold all the form-related keywords, delimited by some character, but it wouldn't look as nice).
It it appropriate to tightly couple a json-schema with a UI, and if it is, is there anything wrong with adding properties to the json-schema like I have described in order to accomplish this?
*I just stumbled across jsonform which is pretty much what I desire, but this question still applies to jsonform as well as a custom parser.
Just to be certain, you are aware there is an optional form object which is used to structure the form output? It allows custom grouping, custom ordering, conditional fields and more ...
https://github.com/joshfire/jsonform/wiki#fields
If your default schema object is satisfactory for both the form layout, as well as how the data object gets stored, then nothing wrong with sticking to the schema for layout of the form.
I am not sure if this answers your question, but the question is slightly unclear to me. Basically yes you can stick to the main schema, but if that is not sufficient for the form layout, you can populate the form object.