jdereg / json-io

Convert Java to JSON. Convert JSON to Java. Pretty print JSON. Java JSON serializer. Deep copy Java object graphs.
Apache License 2.0
329 stars 108 forks source link

Unmarshalling of provided XMLGregorianCalendar implementation class #159

Open pm-finamis opened 2 years ago

pm-finamis commented 2 years ago

Hi, we are using json-io to temporarily store java objects as text values for later processing. In particular, we store webservice request java objects, some of them contain datetime fields of type org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl, which is an XMLGregorianCalendar implementation provided by the application server. json-io fails to unmarshall these fields, returning LinkedHashMap instead of XMLGregorianCalendarImpl. It seems Metautils are not able to see the XMLGregorianCalendarImpl class. As a solution, I added MetaUtils.getNameToClass() method (it returns the private Map<String, Class> nameToClass), then I used it to register the dynamically detected class of the XMLGregorianCalendar implementation class (which is XMLGregorianCalendarImpl). I also provided an instantiator.

     static {
        MetaUtils.getNameToClass().put(
            "org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl",
            (new XMLGregorianCalendarClassFactory()).newInstance(null, null).getClass()
        );

        JsonReader.assignInstantiator(
            "org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl",
            new XMLGregorianCalendarClassFactory());
    }

    public static class XMLGregorianCalendarClassFactory implements JsonReader.ClassFactoryEx {
        @Override
        public Object newInstance(Class aClass, Map map) {
            try {
                return DatatypeFactory.newInstance().newXMLGregorianCalendar();
            } catch (DatatypeConfigurationException e) {
                throw new RuntimeException(e);
            }
        }
    }

Is this the right way to do this in json-io? Would you consider adding MetaUtils.getNameToClass() (or sth similar) to MetaUtils?

Thank you, Regards,

Peter

jdereg commented 2 years ago

In the user guide, look at customization approach #4. That shows how to write a custom reader for json-io. You will likely also want to implement a custom writer. This is the "opening" to allow json-io to serialize any class.

Separately, if you are having trouble instantiating a class, then write an "instantiator" (factory) to create the instance, and use the "assignInstantor" to associate the factory class that can instantiate a class to the actual .class. This is only needed when json-io is failing to instantiate a particular class found in the json input. In those cases, use the "assignInstantor" capability.

pm-finamis commented 2 years ago

Hi John, thanks for your reply. Actually I see no reason to write a custom reader/writer, the default ones work perfectly. It is class lookup that seems to need some customization. (And as I mentioned, I provided an instantiator, but it is used AFTER MetaUtils fail to find the class XMLGregorianCalendarImpl. I guess if MetaUtils were able to find the class, they would be probably also able to instatiate it and instantiator would not be needed anyway.)

jdereg commented 2 months ago

This was a long time ago. Have you resolved this, moved on, other?