-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some convienience methods pls #3
Comments
Thanks :) I think it's probably better to use JSON Pointer syntax for this sort of thing. There's already a private method that resolve a JSON pointer string. One reason I haven't exposed it as a public is just I haven't thought it through much: what's a nice suggestive yet short name? Are there other similar operations that need to be considered and that should work consistently with it (e.g. pattern matching)? How to deal with missing properties...throw an exception or return null or Json.nil()? |
Ahh, yes, Json pointer achieves the same and is more std. Silly of me. Plus it fits nicely with a general REST interface to the signalK model. Why not just overload the 'at' method? Test for / and split if it exists? A json-path implementation (http://goessner.net/articles/JsonPath/) would be nice too :-) |
Right, except that / is a valid JSON string, and therefore object key, character so there is ambiguity with names that start with /. So it has to be another method name. Since it's to be another method name, and we want to be interpreting some expression syntax to retrieve an element elsewhere in the tree, that begs the question shouldn't it be a specific case of a more general path/pattern search function? I've seen JSONPath before and I've thought of it. Thanks for reminding me. I saw it a couple of year ago and though that soon it or something like it would be picked up by a standard body. Unfortunately this hasn't happened. Maybe the right way forward for mJson is to provide an interface to plugin the evaluation of expression within the methods that already exist. For example, while / is a valid string character, it's probably quite rare that it's actually used as part of property names. Or if it is, maybe the dot . character is not used. The Json.Factory interface is already all one needs to change the semantics of JSON object construction and the implementation of JSON entities, entirely...so something similar could take care of the "retrieving information" portion... |
A factory approach works but drops the user into working on mJson extensions (set up project, learn codebase, build,maintain, etc), taking attention away from the real goal, in my case SignalK. How about adding a single additional factory method 'setPathSeparator(char)' The problem I see with JsonPointers is no ability to do wildcards or xpath tests, eg //address/*[city=Nelson]. So JsonPath wins for that.Maybe factory.setJsonPathEvaluation(boolean) would add that? Combined with 'setPathSeparator' would allow both '//address' and '..address' forms of statement. While there may be validity conflicts for some json, the user of mJson would know this when they enabled it, and allow for that when engaging those capabilities? In my use cases I dont currently see the need for complex jsonPaths, just the // and * would suffice |
I'm talking more about defining a new interface, some along the lines of: interface ExpressionEvaluator with a default implementation that could perhaps accept some configuration options. So no need to setup project and customize. This way, the interface of Json itself remains small. Otherwise, methods like set this set that lead to a really bloated interface. I've also thought of having some general configuration Json object so you could set options with Json.opt(name, value). But the main point is that if, after some time, a standard emerges that mJson is going to support without breaking backward compatibility for existing code bases, changing behavior should be a matter of setting up the right evaluator at application startup time. I'm just not sure what that ExpressionEvaluator interface should look like....:) Incidentally, you can already override the 'at' method to do what you want. You need to do the following: class MyFactory extends Json.DefaultFactory But I agree that seems like too much work. In any case, for JSON PAth, certainly a new method or even more is needed. For one thing, since the result of a path is not necessarily a single element, but it actually may be a large number of them, we'd have to return a result-set-like object, e.g. Iterable. |
I really can't think of a better alternative than a general method that evaluates string expressions on a Json and returns the result. Both JSON Pointer and JSONPath are at the end of the day small expression languages that operate on JSON structures. Something that allows transformation would be yet another such expression language. Of course eval(String) is pretty much as general as one can get since everything can be fit under the "evaluate an arbitrary string" abstraction, but I can hardly see the point of having separate methods like "atPath" "pathQuery" "transform". Also, doing the parsing only once is certainly going to be an important performance boost in many cases. So what is needed is an generic interface for expression evaluation that can be plugged into mJson: public class Json public static interface Expression public Json eval(String expresion, Json...options) so one can plug an expression evaluator. A default one would be provided which would detect if we are dealing JSON Pointer or JSONPath and do the right thing. |
Nice work on mJson, I like the concept. Been trying it out and I found I added these pretty quick for big trees. Typing at("person").at(".address").at("city")... gets quite tedious :-)
/**
* Get the Json node at "person.address.city"
* @param path
* @return
/
public Json atPath(String path){
String[] paths = path.split(".");
return atPath(paths);
}
/*
* Get the json node at {"person","address","city"}
* Convenient when using CONSTANTS, atPath(PERSON,ADDRESS,CITY)
* @param path
* @return
*/
public Json atPath(String ... path ){
Json json=null;
for(String k:path){
if(json==null)json=at(k);
json=json.at(k);
if(json==null) return null;
}
return json;
}
The text was updated successfully, but these errors were encountered: