A hack for Query Parameter typing
(“Just Use Jackson YAML Mapper!”)
First, a disclaimer: I do not know if this is a good idea or not — and I definitely do not promote its application, if any, at this point. :)
Background: JSON from not JSON
A user presented me with a use case for Jackson JSON parsing, wherein query parameters can contain String and Number values, like so:
http://foo.bar.com?id=125&name=Bob
and wanted to just parse them into JsonNode
:
JsonNode nameNode = mapper.readTree(request.getParam("name"));
This does not — and should not — work as String Bob
is not valid JSON (all JSON String values MUST be quoted).
But in YAML Norway is False!
But it got me thinking of YAML which is blessed AND cursed by its very loose coercion rules (See “Why is Norway False in YAML?” or countless other articles): basically all of these are not only valid YAML values but also full YAML documents!
Bob
and
1256
and
false
and as such, you actually CAN make it all work with:
YAMLMapper mapper = new YAMLMapper();
JsonNode node = mapper.readTree(queryParamValue);
// Lo + behold! We now got `TextNode`, `NumberNode` or `BooleanNode`!// and to prove it, show it:
System.out.println("Got it: type="+node.getClass().getSimpleName()+" -> "+node.toString());
using “Poor Man’s Type Detection via YAML”.
Given that JsonNode
is generic and not really JSON-specific at all (despite name which is due historical reasons), we can use that to build JSON content, too, should we wish to do that.
Or just detect implied type — keeping in mind that some YAML coercions are sneaking (like afore-referenced JsonNode n = yamlMapper.readTree(“No”); // BooleanNode!
)
And just more trick: in fact you can use “untyped” binding, using nominal target type of Object.class
like so:
Object value = yamlMapper.readValue("137", Object.class);
assertTrue(value instanceof Integer);
which will give you a Number
, String
, Boolean
or null
(or possibly an exception for something more interesting).
Thank you, thank you, thank you — I’m here all week! Tip the Maintainers!