I have the requirement to specify an API in raml where the object properties have to be specified otherwise the validation should fail. This is achieved by additionalProperties: false.
In addition I would like to specify that the request objects can contain pattern properties, similaryl to the official example:
/^note\d+$/?: # restrict any properties whose keys start with "note"
# followed by a string of one or more digits
type: string
Those two things are ok alone, but when brought together they do not work anymore (as specified in the RAML spec):
Moreover, if additionalProperties is false (explicitly or by inheritance) in a given type definition, then explicitly setting pattern properties in that definition is not allowed. If additionalProperties is true (or omitted) in a given type definition, then pattern properties are allowed and further restrict the additional properties allowed in that type.
So the question is how can I achieve this requirement. something like:
types:
Person:
description: |-
Document representing a person.
additionalProperties: false
properties:
firstName?:
description: |-
The person's first name
type: string
/^person_info_.+$/?:
description: Additional person info.
type: string
Please note that this example will fail saying something like
extraneous key [person_info_1] is not permitted
The way I read the RAML specification, it is saying that there are 3 levels of strictness when validating against the properties:
additionalProperties=false: The only allowed properties are the ones declared by the type.
additionalProperties=true AND pattern properties specified : Any additional property name is valid, but IF the name matches the pattern for a pattern property THEN the value must match the value specification for that pattern property.
additionalProperties=true AND no pattern properties specified : Any additional property is valid.
I'm happy to be corrected on the meaning of 2, but that's how the specification seems to read.
Related
I'd like to create a jsonschmema for a yaml file that will contain a list of defined keys to be referenced later in the yaml document.
example
myDef:
foo: bar
baz: lipsum
someProperty:
refferencedValue: foo
the schema should only validate values for someProperty.refferencedValue that are listed in myDef. So only foo and baz would be a valid someProperty.refferencedValue
is this possible with jsonschema? if so what would this look like?
In jsonschema it's not possible to reference arbitrary, dynamic values from the data to use it as part of the schema validation. See this discussion for more context. However:
If you can enumerate all possible properties (or property name patterns) of your myDef object, you can use oneOf to apply specific constraints on the someProperty.refferencedValue value for each property.
If you can't enumerate all the values you can't use standard jsonschema. Some validator libraries implement non-standard features that can help you. For example, Avj implements a $data keyword that can solve your issue. But keep in mind that this solution is tied to Avj - other validators will ignore this keyword.
Spring allows for a given request mapping to specify parameters which must/must not be present or have a certain value. I was wondering if it is possible to assign multiple such parameter conditions to one request mapping like:
Either the parameter is not present or has a certain value.
#GetMapping(
path = ["/data"],
produces = [APPLICATION_JSON_UTF8_VALUE],
params = ["!allStates","allStates=false"]
)
fun getData(){[...]}
It looks like every condition derived from the params are logically linked via an AND.
Additionally it seams like the second condition leads to an implied check for the existence of the parameter, which i do not want.
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-requestmapping-params-and-headers
Is sadly not that specific.
Is there a way to manipulate these params conditions? Or am i better of defining multiple request mappings?
RequestMapping Javadoc is a bit more explicit here.
Note:
... a sequence of "myParam=myValue" style expressions, with a request only mapped if each such parameter is found to have the given value.
So you are right, the conditions are combined with logical AND, and thus separate mappings should be used.
In my use case I have a RAML 1.0 library created by our R&D department that contains definition of multiple data types. Those data types are defined in a generic, parametrized manner so when I reference them in my RAML I do so using following syntax:
type: { resourceTypes.collectionWithCriteria: {itemName: reward, itemCriteria: types.RewardCriteria, itemType : types.RewardList} }
This generates proper GET request with query string defined by types.RewardCriteria and response defined by types.RewardList. It also generates the description for the GET resource defined as: Retrieves the list of <<itemName | !pluralize>>, which ends up being Retrieves the list of rewards.
In my RAML I would like to append additional description to my GET resource, however I 'd rather avoid overwriting library-generated one. Is that possible? I've already tried inline description and using overlay file, both of which simply replace description from the library.
You cannot append for a single value simple property.
The merging rules for traits / resource types state that the description will be replaced:
Every explicit node wins over the ones that are declared in a resource
type or trait. The rest are simply merged.
Also, the merging rules of overlays and extensions states that:.
If the property is a Simple Property
If the property is a Single-value Simple Property,
The property value in the identically named Current Target Tree Object property is replaced with its value from Current Extension Tree Object property.
I am learning GraphQL and one basic point has me puzzled. I know there is an easy explanation, but I can't find it. Specifically, from the Apollo documentation (https://www.apollographql.com/docs/apollo-server/essentials/data.html#operation):
...it makes sense to name the operation in order to quickly identify
operations during debugging or to aggregate similar operations
together...Operations can be named by placing an identifier after the
query or mutation keyword, as we’ve done with HomeBookListing here:
query HomeBookListing {
getBooks {
title
}
}
If HomeBookListing is the name of the query, what, then, is getBooks? The name of the resolver?
Similarly, when you pass variables to a query, why are there "two levels" of parameters, like this
mutation HomeQuickAddBook($title: String, $author: String = "Anonymous") {
addBook(title: $title, author: $author) {
title
}
}
So, would $title: String, $author: String = "Anonymous" be the variables passed to the query, and title: $title, author: $author variables passed to the resolver?
Of course I can memorise the pattern, but I'm keen to understand, conceptually, what the different pieces are doing here. Any insights much appreciated!
You may find it helpful to review the spec, but what follows is a somewhat shorter explanation:
What is an operation?
There are three operations in GraphQL (query, mutation and subscription). Typically, a GraphQL request consists of only one of these three operations, and it forms the root of the request, or the entry point into the rest of the schema.
Each operation has a single object type associated with it. By convention, these types are named Query, Mutation and Subscription, but their naming is functionally irrelevant to your schema. Other than their association with a particular operation, there's nothing special about these object types -- each has a name, description and fields just like any other object type in your schema. Collectively, we call these three types root operation types.
In your example, the query root type has a field called getBooks. That field is resolved according to the same rules as any other field in your schema. The only special thing about this field is that it's at the root -- there is no "parent" field that was resolved before it.
Operation names are optional because they do not impact the data returned by the server -- they are there generally for debugging purposes (although some clients and tools use them to provide other features, so it's always good to have them). Specifying at least one field name for your root operation type, however, is necessary, otherwise your operation would not actually do anything (i.e. query the server for the data). Again, these fields are your entry point into the rest of the schema and the starting point for your data graph.
Ok, but what about the variables?
According to the spec:
Variables must be defined at the top of an operation and are in scope throughout the execution of that operation.
While we do not initialize a variable inside the document with a value, we do need to define it by telling GraphQL what the type of the variable it is. This allows GraphQL to then validate the usages of your variables throughout the document. For example, if you define a variable as a String and then attempt to use it at an input field that is an Int, validation will fail and your request will blow up before it is even executed.
Variables are always defined as part of the operation definition -- they can be used anywhere in the document, though, even multiple times. So there are no "two levels of parameters" here -- one line is simply the definition, the other line is usage.
A word on semantics
Even though we have a spec, the language around GraphQL has evolved past the terms outlined inside it. The term "query" has taken on multiple meanings that you may encounter while reviewing various docs and articles. It helps to keep these definitions in mind to avoid getting confused:
By convention, we name the root operation type associated with the query operation the Query type
Informally, the fields on that Query (i.e. getBooks) that are often referred to as the "queries" of your schema (just like the fields on the Mutation type are often called the "mutations" of your schema.
The complete request string we send to the server, which includes the whole operation and any relevant fragments is officially called the document. However, we often refer to making a request as querying your server. This has led to the document itself often being called a query, whether the operation is contains is actually a query or a different operation like a mutation.
I want to have a class that has a number of fields such as String, Boolean, etc and when the class is constructed I want to have a fieldname associated with each field and verify the field (using regex for strings). Ideally I would just like specify in the constructor that the parameter needs to meet certain criteria.
Some sample code of how :
case class Data(val name: String ..., val fileName: String ...) {
name.verify
// Access fieldName associated with the name parameter.
println(name.fieldName) // "Name"
println(fileName.fieldName) // "File Name"
}
val x = Data("testName", "testFile")
// Treat name as if it was just a string field in Data
x.name // Is of type string, does not expose fieldName, etc
Is there an elegant way to achieve this?
EDIT:
I don't think I have been able to get across clearly what I am after.
I have a class with a number of string parameters. Each of those parameters needs to validated in a specific way and I also want to have a string fieldName associated with each parameter. However, I want to still be able to treat the parameter as if it was just a normal string (see the example).
I could code the logic into Data and as an apply method of the Data companion object for each parameter, but I was hoping to have something more generic.
Putting logic (such as parameter validation) in constructors is dubious. Throwing exceptions from constructors is doubly so.
Usually this kind of creational pattern is best served with one or more factory methods or a builder of some sort.
For a basic factory, just define a companion with the factory methods you want. If you want the same short-hand construction notation (new-free) you can overload the predefined apply (though you may not replace the one whose signature matches the case class constructor exactly).
If you want to spare your client code the messiness of dealing with exceptions when validation fails, you can return Option[Data] or Either[ErrorIndication, Data] instead. Or you can go with ScalaZ's Validation, which I'm going to arbitrarily declare to be beyond the scope of this answer ('cause I'm not sufficiently familiar with it...)
However, you cannot have instances that differ in what properties they present. Not even subclasses can subtract from the public API. If you need to be able to do that, you'll need a more elaborate construct such as a trait for the common parts and separate case classes for the variants and / or extensions.