Closed mmadson closed 8 years ago
Sorry, but no, I was not planning on adding this to the core. This is mainly due to the fact that the spec doesn't cover this and it presents challenges with interoperability.
Forgive my presumptuousness, but please allow me to elaborate my interpretation of Section 2.4.2 of the spec:
An explode ("*") modifier indicates that the variable is to be treated as a composite value consisting of either a list of values or an associative array of (name, value) pairs. Hence, the expansion process is applied to each member of the composite as if it were listed as a separate variable
For my example of expanding query variables above, we are dealing with an associative array of (name,value) pairs:
[("field",["a","b","c"]),("user",[1,2,3])]
The interesting bit to me, though, is that each member of the composite should be treated as if it were listed as a separate variable. So my interpretation is that the variable expansion process should be repeated for each entry in the associative array as if the template had been listed like so:
{?field*}{&user*}
Where both field and user are list template variables.
An explode modifier applied to a list variable causes the expansion to iterate over the list's member values. For path and query parameter expansions, each member value is paired with the variable's name as a (varname, value) pair.
So if my earlier interpretation holds and we repeat the expansion process for each member of the composite, we encounter 2 list variables and according to this section, we should pair each value in the list with the variables' name.
So the result should be
?field=a&field=b&field=c&user=1&user=2&user=3.
I'll admit that the spec definitely doesn't make this clear and it's entirely possible that I'm not reading things correctly, but at the very least I would have expected to be able to supply a custom VarExploder to handle this use case.
If I have time I might try to fork and add this functionality, but I'm curious what your concerns regarding interoperability are so I don't end up wasting my time.
Thanks!
I'd consider this, but I'd suggest issue a PR to the uritemplate-test project which maintains the standard set of test cases for RFC6570. If this is a use case that can be supported by multiple uritemplate processors, I'd definitely add it. But I'd like to avoid adding a custom addition to the spec that only works with this library.
So looking at this more, this isn't going to work with the spec itself. The scenario you've posted wouldn't render the URI you desire. Given:
[("myfield",["a","b","c"]),("myperson",[1,2,3])]
And a template of:
{?field*}{&user*}
You would get something like this:
/?field=myfield&field=field%3Da%26field%3Db%26field%3Dc&user=myperson&user=user%3D1%26user%3D2%26user%3D3
There's a few problems with the spec and nested data structures such as:
However, it should be possible to do this with a VarExploder. The interface is pretty basic as all that it does is force your to expose your data structure as key/value pairs of Strings.
For an example of a custom VarExploder, check out this test case:
and the example implementation:
The JsonVarExploder doesn't do anything fancy, it just converts the JSON into a Map. with a little effort, the JsonVarExploder could be tweaked to satisfy your requirements.
BTW, I seem to have missed your annotation idea when I first read this. That is something worth looking into. Stay tuned...
I've actually implemented this. You can find the test case here:
The output you can expect for your initial test case would be:
/test?field=a,b,c&user=1,2,3
but not this format:
/test?field=a&field=b&field=c&user=1&user=2&user=3
This is now available in the 2.1.5-SNAPSHOT
. I'll release 2.1.5 later in the week once I get a few more negative test cases in place.
I realize nested data structures are not currently supported, are there any plans?
Expected:
OR
Selecting one form or the other could perhaps be an annotation on the composite, for example:
might yield: