我想在render
中json
列出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)
答案 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());