CaiNiaoCoder
CaiNiaoCoder

Reputation: 3319

java Interpret simple expression

I want to extend Gson library to enable field level custom translation, when we translate java bean to json string using gson.

something like this:

@Convert(expression="if(#value == '1') then 'enabled' else 'disabled'")
    private String roleStatus;

How to implement such a expression interpreter in java? Can spring expression do this ?

Upvotes: 1

Views: 1147

Answers (1)

Asif Bhutto
Asif Bhutto

Reputation: 3994

For example your json is as below :

{
   "roleStatus" : "3"
   "role" : "guest"
}

1. First you need to create Converter annotation field level as

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(ElementType.FIELD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Convertor {

    String expression();
}

2. Then parse the gson custom level Deserialization with JsonDeserializer

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import org.mvel2.MVEL;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;

public class RoleStatusDeserializer implements JsonDeserializer<RoleStatus> {

    @Override
    public RoleStatus deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext context) throws JsonParseException {

        final JsonObject jsonObject = json.getAsJsonObject();

        // get roleStatus from jsonObject and populate new roleStatus object
        final RoleStatus roleStatus = new RoleStatus(jsonObject.get("roleStatus").getAsString());

        final String expression = getFiledAnnotationValue();
        // Evaluate expression via Mvel.
        final String result = (String) MVEL.eval(expression, roleStatus);
         // update statusRole
        roleStatus.setRoleStatus(result);

        return roleStatus;
    }

    /**
     * reading Filed level annotation via java reflection
     * @return annoation value
     */
    private String getFiledAnnotationValue() {

        String expression = null;
        for (Field field : RoleStatus.class.getDeclaredFields()) {

            final Annotation annotation = field.getAnnotation(Convertor.class);

            if (annotation instanceof Convertor) {
                field.setAccessible(true);
                Convertor convertorAnnotation = (Convertor) annotation;
                expression = convertorAnnotation.expression();
                field.setAccessible(false);
            }
        }

        return expression;
    }
}

3. get the annotation value(expression) inside RoleStatusDeserializer#deserialize() using java reflection

4.Once you get annotation expression value then you have to evaluate the expression value using MVEL

MVEL is a powerful expression language for Java-based applications, most open source application are using mvel for el such as spring , warp-persist and others. You can download Mvel latest version from Mvel site

5. Finally parse it as

JsonReader reader = new JsonReader(new FileReader("your_path"));
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(RoleStatus.class,new RoleStatusDeserializer());
Gson gson = gsonBuilder.create();
RoleStatus roleStatus = gson.fromJson(reader, RoleStatus.class);

Upvotes: 4

Related Questions