如何在Play框架1.2.x中将List呈现为Json

时间:2014-01-09 21:46:52

标签: json playframework

我想在renderjson列出play framework 1.2.x列表。当我从网上搜索时,我发现使用了Gosn。但无论如何它并没有帮助我。我需要在object list中将任何json呈现为controller action。这是我的代码和错误跟踪。

@Entity(name="country")
public class Country extends Model{
    public String name;
    public String code;

     @OneToMany(mappedBy="country", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
     public List<City> cities;
}

@Entity
public class City extends Model{
    public String name;
    public String code;
    @ManyToOne
    public Country country;
}


public static void ajaxGetCities(long countryid){
    List<City> cities = City.find("byCountry_id", countryid).fetch();
    renderJSON(cities);
}


at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)

1 个答案:

答案 0 :(得分:1)

这似乎是一个循环引用问题。当gson尝试在列表中序列化City对象(例如,City A)时,它会找到Country对象,因此它也会尝试序列化Country对象。但是,Country对象中有许多City对象引用,其中一个引用指向City A.所以这里有一个引用循环。

在您的案例中,有两种方法可以解决循环引用:

一个。删除Country对象中City对象的引用。

    @OneToMany(mappedBy="country", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    public List<City> cities;

OneToMany对我来说是多余的,因为我总能通过City Object中的静态方法找到Country的城市。

B中。保留cities字段并实施CountrySerializer以防止在gson中进行循环引用。

    public class CountrySerializer implements JsonSerializer<Country> {

        public JsonElement serialize(User src, Type typeOfSrc, JsonSerializationContext context) {
            Gson gson = new GsonBuilder()
                .setExclusionStrategies(new LocalExclusionStrategy()).create();
            return gson.toJsonTree(src);
        }   

        public static class LocalExclusionStrategy implements ExclusionStrategy {
            public boolean shouldSkipClass(Class<?> clazz) {
                return false;
            }   

            public boolean shouldSkipField(FieldAttributes f) {
                // add exlusion rules here:
                // exclude field whose name is "cities"
                return f.getName().toLowerCase().equals("cities");
            }   
        }   
    }

使用它:

    public static void ajaxGetCities(long countryid){
        List<City> cities = City.find("byCountry_id", countryid).fetch();
        renderJSON(cities, new CountrySerializer());
    }

如果返回对象中有复杂的结构,则可以同时使用多个序列化程序。

    renderJSON(cities, new CountrySerializer(), new CodeSerializer());