flexjson deserialize property string with dot "." inside

1.9k views Asked by At

I'm trying to use flexjson to deserialize a string I get from a web call. The problem is that a few elements in there have a dot in the property/key for example:

[{... 
       "contact.name": "Erik Svensson", 
       "contact.mail": "[email protected]",
       "contact.phone": "0731123243", 
...}]

Now everything else falls in place except these strings with the dots, they end up null in my target class. I'm guessing it's because it doesn't know what to map them to as I can't declare a variable in my container class that has a dot.

This is the code I'm runnign to deserialize now,

mData = new JSONDeserializer<List<Thing>>()
  .use("values", Thing.class)
  .deserialize(reader);

How do I modify this to catch the strings with the dot and put them in my Things class as:

String contactName; 
String contactMail;
String contactPhone;

// getters&setters

Note I don't have any control over the Serialization..

2

There are 2 answers

0
dadoz On

OK So I've solved this but I had to abandon flexJson. Searched all over the place for a simple way but couldn't find one.

Instead I went with Jackson and this is what I ended up with:

ObjectMapper mapper = new ObjectMapper();
mThings = mapper.readValue(url, new TypeReference<List<Thing>>() {});

And in my class Thing:

@JsonProperty("contact.name")
private String contactName;

@JsonProperty("contact.mail")
private String contactMail;

@JsonProperty("contact.phone")
private String contactPhone;

// getters and setters..

If anyone knows how to do this with FlexJson feel free to post an answer, I would like to see it.

0
jCoder On

As I was curious, too, if this type of assignment can be done easily, I've played with some code, and this is what I came up with. (I'm posting it here because maybe it's helpful for somebody having some related question, or just as a point to start from.)

The PrefixedObjectFactory (see below) will cut off a fixed prefix from the JSON object's field name and use this name to find a matching bean property. The code can be easily changed to do a replacement instead (e.g. setting the first letter after a . to uppercase and remove the .)

It can be used like this:

List<Thing> l = new JSONDeserializer<List<Thing>>().use("values", new PrefixedObjectFactory(Thing.class, "contact.")).deserialize(source);

The code:

import flexjson.ObjectBinder;
import flexjson.ObjectFactory;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Type;
import java.util.Map;

public class PrefixedObjectFactory<T> implements ObjectFactory {

    protected Class<T> clazz;
    protected String prefix;

    public PrefixedObjectFactory(Class<T> c, String prefix) {
        this.clazz = c;
        this.prefix = (prefix == null) ? "" : prefix;
    }

    @Override
    public Object instantiate(ObjectBinder context, Object value, Type targetType, Class targetClass) {
        try {
            Class useClass = this.clazz;
            T obj = (T)useClass.newInstance();
            if (value instanceof Map) {
                // assume that the value is provided as a map
                Map m = (Map)value;
                for (Object entry : m.entrySet()) {
                    String propName = (String)((Map.Entry)entry).getKey();
                    Object propValue = ((Map.Entry)entry).getValue();
                    propName = fixPropertyName(propName);
                    propValue = fixPropertyValue(propValue);
                    assignValueToProperty(useClass, obj, propName, propValue);
                }
            } else {
                // TODO (left out here, to keep the code simple)
                return null;
            }
            return obj;
        } catch (Exception ex) {
            return null;
        }
    }

    protected String fixPropertyName(String propName) {
        if (propName.startsWith(this.prefix)) {
            propName = propName.substring(this.prefix.length());
        }
        return propName;
    }

    protected Object fixPropertyValue(Object propValue) {
        return propValue;
    }

    protected PropertyDescriptor findPropertyDescriptor(String propName, Class clazz) {
        try {
            return new PropertyDescriptor(propName, clazz);
        } catch (Exception ex) {
            return null;
        }
    }

    protected void assignValueToProperty(Class clazz, Object obj, String propName, Object propValue) {
        try {
            PropertyDescriptor propDesc = findPropertyDescriptor(propName, clazz);
            if (propDesc != null) {
                propDesc.getWriteMethod().invoke(obj, propValue);
            }
        } catch (Exception ex) {
        }
    }
}