将整个类序列化为String字段而不是JSON对象

时间:2014-10-26 21:36:32

标签: java java-ee jaxb jax-rs jboss-eap-6

我有一个对象使用类实例作为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" } }

编辑:看看杰克逊常见问题我找到了一些有用的东西,我想要的东西可能与我发现的东西相当,但在中的JAX-RS / Java EE 6环境 JBoss EAP 6.1 。使用 JBoss EAP 6.1 在我的类路径中没有任何@JsonValue

http://wiki.fasterxml.com/JacksonFAQ#Serializing_values_as_simple_types

1 个答案:

答案 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;
    }
}

结果

enter image description here

获取相关性

如果您使用的是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添加到项目中。测试了这种方法,结果相同

enter image description here

如果您在添加依赖项时遇到任何问题,请与我们联系。


更新:不使用Jackson(没有第三方依赖)

我们可以使用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"}