Java 在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

我发现的所有关于JSON的web文章似乎都和数据规范有关;我正在寻找一个清晰的方法来实现的提示

我有一个从Hibernate获得的持久对象和一个web服务,该服务应该返回它们的列表

生成的JSON应该包含与数据混合的HATEOAS链接。JSON库不应该触发任何错误(解析任何代理),而是将它们转换为
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));
    }
}