开发者

How to expose a method using GSon?

开发者 https://www.devze.com 2023-04-04 15:27 出处:网络
Using Play Framework, I serialize my models via GSON. I specify which fields are exposed and which aren\'t.

Using Play Framework, I serialize my models via GSON. I specify which fields are exposed and which aren't.

This works great but I'd also like to @expose method too. Of course, this is too simple.

How can I do it ?

Thanks for y开发者_StackOverflowour help !

public class Account extends Model {
    @Expose
    public String username;

    @Expose
    public String email;

    public String password;

    @Expose // Of course, this don't work
    public String getEncodedPassword() {
        // ...
    }
}


The best solution I came with this problem was to make a dedicated serializer :

public class AccountSerializer implements JsonSerializer<Account> {

    @Override
    public JsonElement serialize(Account account, Type type, JsonSerializationContext context) {
        JsonObject root = new JsonObject();
        root.addProperty("id", account.id);
        root.addProperty("email", account.email);
        root.addProperty("encodedPassword", account.getEncodedPassword());

        return root;
    }

}

And to use it like this in my view:

GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(Account.class, new AccountSerializer());
Gson parser = gson.create();
renderJSON(parser.toJson(json));

But having @Expose working for a method would be great: it would avoid making a serializer just for showing methods!


Check out Gson on Fire: https://github.com/julman99/gson-fire

It's a library I made that extends Gson to handle cases like exposing method, results Post-serialization, Post-deserialization and many other things that I've needed over time with Gson.

This library is used in production in our company Contactive (http://goo.gl/yueXZ3), on both Android and the Java Backend


Gson's @Expose seem to only be supported on fields. There is an issue registered on this: @Expose should be used with methods.


Couple different options based on Cyril's answer:

Custom serializer with a shortcut:

public static class Sample
{
    String firstName = "John";
    String lastName = "Doe";

    public String getFullName()
    {
        return firstName + " " + lastName;
    }
}

public static class SampleSerializer implements JsonSerializer<Sample>
{
    public JsonElement serialize(Sample src, Type typeOfSrc, JsonSerializationContext context)
    {
        JsonObject tree = (JsonObject)new Gson().toJsonTree(src);
        tree.addProperty("fullName", src.getFullName());
        return tree;
    }
}

public static void main(String[] args) throws Exception
{
    GsonBuilder gson = new GsonBuilder();
    gson.registerTypeAdapter(Sample.class, new SampleSerializer());
    Gson parser = gson.create();
    System.out.println(parser.toJson(new Sample()));

}

-OR- Annotation based serializer

public static class Sample
{
    String firstName = "John";
    String lastName = "Doe";

    @ExposeMethod
    public String getFullName()
    {
        return firstName + " " + lastName;
    }
}

public static class MethodSerializer implements JsonSerializer<Object>
{
    public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context)
    {
        Gson gson = new Gson();
        JsonObject tree = (JsonObject)gson.toJsonTree(src);

        try
        {               
            PropertyDescriptor[] properties = Introspector.getBeanInfo(src.getClass()).getPropertyDescriptors();
            for (PropertyDescriptor property : properties)
            {
                if (property.getReadMethod().getAnnotation(ExposeMethod.class) != null)
                {
                    Object result = property.getReadMethod().invoke(src, (Object[])null);
                    tree.add(property.getName(), gson.toJsonTree(result));
                }
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }

        return tree;
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) //can use in method only.
public static @interface ExposeMethod {}

public static void main(String[] args) throws Exception
{
    GsonBuilder gson = new GsonBuilder();
    gson.registerTypeAdapter(Sample.class, new MethodSerializer());
    Gson parser = gson.create();
    System.out.println(parser.toJson(new Sample()));

}
0

精彩评论

暂无评论...
验证码 换一张
取 消