Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
527 views
in Technique[技术] by (71.8m points)

grails - Way to deep traverse a Groovy object with dot in string using GPath

The situation I have is that I'm querying MongoDB with a string for a field that is more than one level deep in the object hierarchy. This query must be a string. So for example I'm querying for something like this in Groovy:

def queryField = 'a.b.c'  //this is variable and can be different every time
def result = mongodb.collection.findOne([queryField:5])

The problem no arises that in the result I want to find the value of the nested field. With GPath I could go one level deep and get a's value doing this

def aObj = result."a"  //or result["a"]

However I want to go deeper than that by doing something like this:

def queryField = "a.b.c"       //this can change every time and is not always 'a.b.c'
def cObj = result[queryField]  //since field is variable, can't just assume result.a.b.c

This does not work in Groovy right now. There is a bug logged here, but I was wondering if there is a better work around to use for this scenario that is a bit cleaner than me parsing the string by splitting on the dot and then building the object traversal. Note that "a.b.c" is variable and unknown at runtime (e.g. it could be "a.b.d").

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Based on the bug/thread it would appear there are some ambiguity problems with supporting a dotted property accessor. Based on the mailing list thread it would seem that evaluating the queryField string would be your best bet:

def result = [a: [b: [c: 42]]]
def queryString = 'a.b.c'

def evalResult = Eval.x(result, 'x.' + queryString)
assert evalResult == 42

Script on Groovy Web Console

The mailing list thread is a little old, so there's a new-ish (since at least 1.7.2) Eval class that can help out with running small snippets that don't have a large binding.

Otherwise, you can split the string and recursively do property evaluations on the object, effectively reproducing a subset of GPath traversal behavior.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...