#8 Allow bean processors to use json-lib's default processor

closed-fixed
aalmiray
None
5
2010-12-01
2008-09-26
Scott Bronson
No

I have some processors that only occasionally need to modify the way a bean is processed. As far as I can tell, json-lib offers no way for a processor to say, "never mind -- process this bean the way you normally would."

This patch just extracts the default behavior out to a separate call. That way, a processor can do something like this:

public final class NopProcessor implements JsonBeanProcessor {
public JSONObject processBean(Object bean, JsonConfig jsonConfig) {
// ask json-lib to render the bean as it normally would.
if(special_case) {
return getSpecialFormatting(bean);
}
return JSONObject.defaultBean(bean, jsonConfig);
}
}

I didn't know whether to call it defaultBeanRenderer, defaultBeanSerializer, ... Hopefully you can pick a better name for the method.

Discussion

  • Scott Bronson
    Scott Bronson
    2008-09-26

    Dang, that example didn't come out right. Let me try again:

    <pre>
    public final class OccasionalProcessor implements JsonBeanProcessor {
    public JSONObject processBean(Object bean, JsonConfig jsonConfig) {
    if(special_case) {
    // sometimes we need to format this bean our way
    return getSpecialFormatting(bean);
    }
    // and sometimes we want json-lib to render it as usual.
    return JSONObject.defaultBean(bean, jsonConfig);
    }
    }
    </pre>

     
  • aalmiray
    aalmiray
    2008-09-29

    Scott, what you describe can be a bit tricky to implement, there is a simpler alternative though, have your JsonBeanProcessor receive a reference to a JsonConfig instance (make sure you make a copy of it with JsonConfig.copy()), be sure remove the processor from the copy. Now whenever your processor is called and if you need to handle the special case then just call JSONObject.fromObject( bean, jsonConfigCopy )

    Cheers,
    Andres

     
  • aalmiray
    aalmiray
    2008-09-29

    • assigned_to: nobody --> aalmiray
     
  • Scott Bronson
    Scott Bronson
    2008-10-01

    Your alternative assumes that I want the default processing for *all* nested objects of the same type. Unfortunately, that's not true. I want the default processing for *only* the root objects in an array, I still need to custom render the nested objects.

    Picture a nested array of friends... There are cycles all over it (bob is friends with harry who is friends with bob who is friends with harry ...) I want to use the default processing for the root friend ("Bob"), so all his attributes are displayed, but I only want to display the ID of all the rest of the friends ("Harry"). That way I only go one level deep and there are no cycles.

     
  • aalmiray
    aalmiray
    2008-10-02

    Could you send a failing testcase with your expectations? that will help us understand better your problem.
    Also wouldn't a cycleDetectionStrategy help you in this case too?

    Cheers,
    Andres

     
  • I have a similar situation where I want to use the default processor at times and a custom processor at others. My initial thought was to do something similar to what you suggested on 2008-09-29, though it doesn't seem to work because a cycle is detected. I'm using 2.3-jdk15 and my code looks like:

    config.registerJsonBeanProcessor(Object.class, new JsonBeanProcessor() {
    public JSONObject processBean(Object bean, JsonConfig jsonConfig) {
    JsonConfig setterBasedConfig = new JsonConfig();
    setterBasedConfig.setJsonPropertyFilter(S_SETTABLE_PROPERTY_FILTER);
    JSONObject ret = JSONObject.fromObject(bean, setterBasedConfig);
    if (ret.isEmpty()) {
    // might not have setter methods - look at fields via reflection
    }
    return ret;
    }
    });
    return JSONSerializer.toJSON(data, config).toString();

    When I run this I get a cycle detection error because the bean is already in the CycleSet when it enters my processor, and when I call back out to fromObject it is encountered again and treated as a cycle. I can't think of another way around this - the CycleSet looks like it is protected pretty well so I can't remove/add the bean in my processor.

    Unlike Scott I do want this to work recursively. Has the codebase changed since your suggestion on 2008-09-29 to not allow this approach, or am I missing something?

    Thanks,
    Bryan

     
  • aalmiray
    aalmiray
    2010-12-01

    • status: open --> closed-fixed
     
  • aalmiray
    aalmiray
    2010-12-01

    Patch modified (for jdk5 compatibility) and applied. Thank you!