我有一个对象使用类实例作为String类型的包装器。如何使用JAX-RS和Java EE 6将我的类序列化为JSON对象,只使用toString()方法而不为类和每个字段创建JSON对象?
要序列化的类:
public class Text {
private String content;
protected Text( String content ) {
this.content = content;
}
public static Text from( String content ) {
return new Text( "The text content");
}
// This is a method that is used by the subclass and has no meaning for serialization
protected String getContent() {
return content;
}
// This should be used to serialize this class into a String, instead of an object
@Override
public String toString() {
return content;
}
}
使用要序列化的类的父类:
public class EditorStoryChapterInput {
private Text title;
public Text getTitle() {
return title;
}
}
预期结果:我希望序列化为{ "title": "The text content" }
而不是{ "title": { content: "the text content" } }
。
@JsonValue
:
http://wiki.fasterxml.com/JacksonFAQ#Serializing_values_as_simple_types
答案 0 :(得分:1)
来自评论:
我不知道是否符合规范,但我只是对它进行了测试,将Jackson依赖项添加到我的项目中,并将
@JsonValue
放在toString()
上,如the link中提到的那样,它工作正常。就像我说的那样,JBoss正在使用Jackson来进行序列化。所以在你的项目中使用它并没有错。您只需要添加依赖项以编译注释。如果需要,您可以直接从服务器模块获取。但是使用Maven会更容易
以下是我用于示例的类。我将发布这些类,然后指出如何获取依赖项。
您的Text
班级
/** Getter and Setters added for Jackson discovery **/
public class Text {
private String content;
public void setContent(String content) { this.content = content; }
protected String getContent() { return content; }
@Override @JsonValue
public String toString() { return content; }
}
您的EditorStoryChapterInput
班级
public class EditorStoryChapterInput {
private Text title;
public void setTitle(Text title) { this.title = title; }
public Text getTitle() { return title; }
}
资源类
@Path("/json")
public class JsonResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getJson() {
EditorStoryChapterInput input = new EditorStoryChapterInput();
Text title = new Text();
title.setContent("Hello World");
input.setTitle(title);
return Response.ok(input).build();
}
}
注册资源的Application
类
@ApplicationPath("/rest")
public class JsonApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(JsonResource.class);
return classes;
}
}
结果
获取相关性
如果您使用的是Maven,则只需要jackson-core-asl
工件。当我使用JBoss时,我更喜欢使用他们的boms,因此他们可以管理版本。所以你的pom看起来像什么(记住我说我们可以使用provide
范围,因为JBoss已经有了这些依赖关系。我们只需要它来编译)
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-javaee-6.0-with-resteasy</artifactId>
<version>1.0.7.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<scope>provided</scope>
</dependency>
... Other dependencies
</dependencies>
如果你没有使用Maven,你可以简单地看一下
${eap-home-dir}\modules\system\layers\base\org\codehaus\jackson\jackson-core-asl\main
在那里你会找到jackson-core-asl-1.9.9.redhat-3.jar
。只需将其添加到项目中,但通常会将jar添加到项目中。测试了这种方法,结果相同
如果您在添加依赖项时遇到任何问题,请与我们联系。
我们可以使用Java API for JSON Processing,并实现我们自己的MessageBodyWriter
,将EditorStoryChapterInput
对象写入响应OutputStream
。它可能看起来像
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class TextMessageBodyWriter
implements MessageBodyWriter<EditorStoryChapterInput> {
@Override
public boolean isWriteable(Class type, Type type1,
Annotation[] antns, MediaType mt) {
return type == EditorStoryChapterInput.class;
}
@Override
public long getSize(EditorStoryChapterInput t, Class<?> type,
Type type1, Annotation[] antns, MediaType mt) {
return -1;
}
@Override
public void writeTo(EditorStoryChapterInput input, Class<?> type,
Type type1, Annotation[] antns, MediaType mt,
MultivaluedMap<String, Object> mm, OutputStream out)
throws IOException, WebApplicationException {
Text title = input.getTitle();
JsonObject jsonObject =
Json.createObjectBuilder()
.add("title", title.toString()).build();
try (JsonWriter jsonWriter = Json.createWriter(out)) {
jsonWriter.writeObject(jsonObject);
}
}
}
在搜索MessageBodyWriters
时,JAX-RS将查看@Produces
注释以查看它产生的类型,如果它与我们的资源方法上的@Produces
方法匹配,则编写器将被列入框架列表以进行遍历。接下来,它将检查每个编写器上的isWritable
方法。如果它返回true,那么它就是它将使用的编写器。在我们的例子中,如果响应主体的返回类型是EditorStoryChapterInput
类型,则返回true。
在writeTo
方法中,我们使用Java JSON Processing API创建JsonObject
并将其写入框架提供给我们的OutputStream
。
然后我们可以使用应用程序注册编写器
@ApplicationPath("/rest")
public class TextApplication extends Application {
@Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(JsonResource.class);
classes.add(TextMessageBodyWriter.class);
return classes;
}
}
使用上面的相同JsonResource
类对其进行测试,我们得到输出
{"title":"Hello World"}