A few suggestions here.
* This should not be called VarRefToJson, because it doesn't convert a VarRef to a JsonElement. Such a function should have the signature JsonElement *VarRefToJson(const VarRef *ref);
* It appears that this function does 3 things: (1) Qualify a VarRef, (2) Lookup a variable, (3) Convert a Variable value to Json. I realize that this reduces code duplication, because several functions follow this pattern, but at the cost of having an pretty complex function (inflexible). I would retain (1) in callers (because I think functions should make an explicit choice about this), then make a function a function with the rest that is named something really complicated (reflecting that it makes a bunch of assumptions): static JsonElement *LookupVariableAndConvertToJson(const EvalContext *ctx, const VarRef *ref); (preferably dropping the type filtering if you don't strictly need it, otherwise see other comment).