Java 在JSON中呈现休眠对象?
我发现的所有关于JSON的web文章似乎都和数据规范有关;我正在寻找一个清晰的方法来实现的提示 我有一个从Hibernate获得的持久对象和一个web服务,该服务应该返回它们的列表 生成的JSON应该包含与数据混合的HATEOAS链接。JSON库不应该触发任何错误(解析任何代理),而是将它们转换为Java 在JSON中呈现休眠对象?,java,json,spring,hibernate,Java,Json,Spring,Hibernate,我发现的所有关于JSON的web文章似乎都和数据规范有关;我正在寻找一个清晰的方法来实现的提示 我有一个从Hibernate获得的持久对象和一个web服务,该服务应该返回它们的列表 生成的JSON应该包含与数据混合的HATEOAS链接。JSON库不应该触发任何错误(解析任何代理),而是将它们转换为href属性 因此,如果我有两个Customer实例和一个名为/customers的web服务,我应该得到如下所示的JSON: { "href" : "/customers", "dat
href
属性
因此,如果我有两个Customer实例和一个名为/customers的web服务,我应该得到如下所示的JSON:
{
"href" : "/customers",
"data" : [ { "id" : 234,
"name" : "Bill Shatner",
"href" : "/customers/234",
"orders" : "/customers/234/orders",
"orders-count" : 2
},
{
"id" : 210,
"name" : "Malcolm Reynolds",
"href" : "/customers/210",
"orders" : "",
"orders-count" : 0
} ]
}
(注意:只是一个说明,没有编码到任何规范,如HAL等)
我觉得我不得不在服务中手动滚动所有这些东西,这感觉像是缺乏经验。当然有一个代理感知的web框架,允许我创建一个JSON模板,并将其传递给我的域对象,并期望得到正确的结果
@Path("/customers")
public HttpResponse getAllCustomers(HttpRequest req)
{
@Autowired CustomerRepository custRepo;
List<Customer> data = custRepo.findAll();
return ResponseBuilder.status(200).toJSON(data).build();
}
@Path(“/customers”)
公共HttpResponse getAllCustomers(HttpRequest请求)
{
@自动连线客户存储库;
列表数据=custRepo.findAll();
返回ResponseBuilder.status(200).toJSON(data.build();
}
我知道这可能比可能的更神奇,但肯定有比为每个持久对象创建一个
HashMap
更好的方法,将每个getter硬编码到put
中,并在一个大的galumphing循环中添加硬编码的href字符串 我使用Gson lib实现Json转换器,因此您不仅可以与所有休眠对象一起使用,还可以创建抽象类或接口,并使所有休眠对象实现此接口,请检查此示例:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonConvertor {
private static GsonBuilder gsonBuilder;
private static Gson gson;
private JsonConvertor() {
}
public static Object fromJson(String json, Class clz)
{
gson=new Gson();
return gson.fromJson(json,clz);
}
public static String toJson(Object obj,List<String> fields) {
gsonBuilder = new GsonBuilder();
gsonBuilder = gsonBuilder
.addSerializationExclusionStrategy(new CustomIclusionStrategy(fields));
gson = gsonBuilder.create();
String json = gson.toJson(obj);
return json;
}
public static String toJson(Object obj) {
gsonBuilder = new GsonBuilder();
gsonBuilder = gsonBuilder
.addSerializationExclusionStrategy(new CustomIclusionStrategy(null));
gson = gsonBuilder.create();
String json = gson.toJson(obj);
return json;
}
}
class CustomIclusionStrategy implements ExclusionStrategy {
private List<String> fields;
public CustomIclusionStrategy(List<String> fields) {
this.fields = fields;
}
// called only if shouldSkipClass returns false
@Override
public boolean shouldSkipField(FieldAttributes f) {
if(fields!=null && fields.contains(f.getName()))
{// exclude
return true;
}
// include in generating JSON
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// if returns false shouldSkipField will be called, otherwise shouldSkipField will not be called
return false;
}
}
这是示例对象:
public class B {
private int salary;
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
public class A {
private int id;
private String name;
private B b;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
}
下面是一个如何从生成JSON中排除字段的示例
public class Test {
public static void main(String[] args) {
A a=new A();
a.setId(1);
a.setName("safwa");
a.setB(new B());
List<String> fields=new ArrayList<String>();
fields.add("b");
System.out.println("Exclusion: "+JsonConvertor.toJson(a,fields));
System.out.println("NO Exclusion: "+JsonConvertor.toJson(a));
}
}
公共类测试{
公共静态void main(字符串[]args){
A=新的A();
a、 setId(1);
a、 setName(“safwa”);
a、 setB(新B());
列表字段=新的ArrayList();
字段。添加(“b”);
System.out.println(“排除:+JsonConvertor.toJson(a,字段));
System.out.println(“无排除:+JsonConvertor.toJson(a));
}
}
实际上,除了正常的JSON支持之外,Spring还提供了一种实现基于HATEOAS的rest服务的简单方法。看看这个。看看问候语
模型类<代码>导入org.springframework.hateoas.ResourceSupport代码>。如果从ResourceSupport
扩展POJO类。一些静态方法是可用的,它允许您将这些HREF添加到正常的JSON响应之上。那么您是说您希望将列表数据
作为JSON返回吗?如果是,则只需将Spring请求映射的返回类型设置为@ResponseBody List
。在类路径中包含Jackson库。您的列表将作为JSON响应返回,您可以找到更多详细信息@Amit.rk3,这是否添加了self和lazy has-a的URL?它会避免解析代理吗?只是找到了一个更好的方法。把它贴在回信上。我认为这应该对你有用。看来你答案的核心是排除策略。toJson(对象)没有深度控制,因此它将循环所有代理并解析它们。它也不会为自包含列表添加URL-您将如何做到这一点?如何实现排除策略以避免解析代理?解析代理是什么意思?能否添加有关该问题的示例,以便我们能够解决代理本质上是一个部分膨胀、延迟获取的持久对象:它只有“id”值,并将导致数据库查询(或者3,如果相信我的日志文件的话)任何其他价值。解析它们意味着执行数据库查询以获取所有值。通常代理本身有关系,所以如果没有深度控制,就像在Gson中一样,您可以只为一行5列实现数据库的一半!所以您需要深入,并为关系中的对象生成JSON?不,默认情况下Gson是深入的。我希望它不要这样做,只需返回5个值和一个带有id
的代理链接即可。我不想让它引起更多的数据库工作。我在搜索时看到了这一点,但这似乎是一种“如果你想使用它,就放弃所有现有工作”的解决方案。依赖项堆栈很大,没有集成到现有的Spring解决方案中(我担心它会破坏已经存在的其他解决方案)。另外,这个示例不是真实的:没有处理/返回HTTP状态代码的规定<代码>问候语注释过多:它几乎等同于在每个域对象上硬编码toJson()方法。另外,它破坏了SOC:域对象应该(不)知道视图表示(json流)。这迫使DAL jar中的依赖项发生巨大(不受欢迎)变化。
public class Test {
public static void main(String[] args) {
A a=new A();
a.setId(1);
a.setName("safwa");
a.setB(new B());
List<String> fields=new ArrayList<String>();
fields.add("b");
System.out.println("Exclusion: "+JsonConvertor.toJson(a,fields));
System.out.println("NO Exclusion: "+JsonConvertor.toJson(a));
}
}