1
package fr.zenexity.json;
3
import fr.zenexity.json.JSON.FieldWrapper;
4
import fr.zenexity.json.JSONTokenizer.Token;
5
import java.io.IOException;
6
import java.lang.reflect.Field;
7
import java.lang.reflect.Modifier;
8
import java.lang.reflect.Type;
9
import java.util.HashMap;
10
import java.util.HashSet;
13
import java.util.logging.Level;
14
import java.util.logging.Logger;
15
import static fr.zenexity.json.JSONTokenizer.Token.*;
17
class BeanBinder implements JSONBinder {
19
private static final Logger log = Logger.getLogger("fr.zenexity.json");
20
private Class forClass;
21
private Map<String, FieldWrapper> fields = new HashMap<String, FieldWrapper>();
23
public BeanBinder(Class forClass) {
25
this.forClass = forClass;
30
* Introspect the bean class for properties and getters/setters
31
* Field informations are cached in a {@link FieldWrapper FieldWrapper} structure
33
private void initialize() {
34
Set<Field> fieldset = new HashSet<Field>();
35
findAllFields(forClass, fieldset);
36
for (Field field : fieldset) {
37
if (isSettable(field)) {
38
FieldWrapper fw = new FieldWrapper(field, forClass);
39
field.setAccessible(true);
40
// todo there is a problem here if a superclass define a private field with same name
41
fields.put(field.getName(), fw);
46
public static void findAllFields(Class clazz, Set<Field> found) {
47
Field[] fields = clazz.getDeclaredFields();
48
for (int i = 0; i < fields.length; i++) {
51
Class sClazz = clazz.getSuperclass();
52
if (sClazz != null && sClazz != Object.class) {
53
findAllFields(sClazz, found);
57
public Object read(Class<?> clazz, Type type, JSONReader reader) {
58
Token tok = reader.assertIs(START_MAP);
60
Object instance = clazz.newInstance();
61
tok = reader.nextToken();
66
String key = tok.value;
67
tok = reader.nextToken();
68
reader.assertIs(SEMICOLON);
69
FieldWrapper wrapper = fields.get(key);
70
if (wrapper == null) {
71
log.fine("no field " + key + " in bean " + clazz.getSimpleName() + " : skipping json data");
74
tok = reader.nextToken();
75
Object value = reader.readInternal(wrapper.field.getName(), wrapper.field.getType(), wrapper.field.getGenericType(), tok);
77
wrapper.setValue(instance, value);
78
} catch (Exception e) {
79
log.log(Level.SEVERE, "unable to set field value for " + wrapper.field, e);
83
tok = reader.nextToken();
87
reader.assertIs(COMMA);
88
tok = reader.nextToken();
91
} catch (JSONException pex) {
93
} catch (Exception ex) {
94
throw JSONException.bindError("beanbinder failure", ex, reader.getParser());
98
public boolean isSettable(Field field) {
99
final int unmodifiable = Modifier.STATIC + Modifier.NATIVE + Modifier.FINAL + Modifier.TRANSIENT;
100
return (field.getModifiers() & unmodifiable) == 0;
103
public void write(Object obj, JSONWriter jsonWriter) {
107
jsonWriter.writeChar('{');
108
keys = fields.keySet();
109
for (String fieldname : keys) {
111
jsonWriter.writeChar(',');
113
FieldWrapper wrapper = fields.get(fieldname);
114
jsonWriter.writeString(fieldname);
115
jsonWriter.writeChar(':');
116
log.fine("field:"+fieldname+" wrapper:"+wrapper);
117
jsonWriter.write(wrapper.getValue(obj));
119
jsonWriter.writeChar('}');
121
} catch (IOException ex) {
122
log.log(Level.SEVERE, null, ex);