java - ObjectMapper writeValueAsString 更改字节缓冲区 pos

标签 java

我正在尝试使用 ObjectMapper 记录响应,将复杂对象序列化为字符串,其中某处包含字节缓冲区。 这会更改字节缓冲区内的光标位置并简单地破坏响应。

我正在使用的代码片段:

import org.codehaus.jackson.map.ObjectMapper;

private static final ObjectMapper MAPPER = new ObjectMapper();

public static String serializeToString(final Object obj) {
    Preconditions.checkArgument(obj != null, "Object to be serialized is null");
    try {
        final String str = MAPPER.writeValueAsString(obj);
        if (Strings.isNullOrEmpty(str)) {
            log.warn("Serialized to null/empty string");
        }
        return str;
    } catch (final JsonGenerationException e) {
        throw new IllegalArgumentException("Json generation exception occured in de-serializing obj", e);
    } catch (final JsonMappingException e) {
        throw new IllegalArgumentException("Json mapping exception occured in de-serializing obj", e);
    } catch (final IOException e) {
        throw new IllegalArgumentException("IO exception occured in de-serializing obj", e);
    }
}

我向上面的方法传递了一个内部有字节缓冲区的复杂对象。 我在调用上述方法之前和之后打印了字节缓冲区。

public static void main(final String[] args) throws SecurityException, NoSuchMethodException {
    final String x =
            "Random data i am using for this test for byte buffer. Random data i am using for this test for byte buffer";
    final byte[] byteArr = x.getBytes();
    final ByteBuffer bb = ByteBuffer.wrap(byteArr);
    System.out.println("before bytebuffer :" + bb);
    String stringData = SerializerUtil.serializeToString(bb); // In real i am passing a complex structure having
                                                              // bytebuffer inside
    System.out.println(stringData);
    System.out.println("after bytebuffer :" + bb);
}

输出:

before bytebuffer :java.nio.HeapByteBuffer[pos=0 lim=106 cap=106]

{"short":21089,"char":"\u6e64","int":1869422692,"long":7022344510808023405,"float":2.0790493E-19,"double":6.687717052371733E223,"direct":false,"readOnly":false}

after bytebuffer :java.nio.HeapByteBuffer[pos=28 lim=106 cap=106]

(pos=0 到 pos=28)位置的这种变化只会破坏发送的响应。我们有没有办法在不影响 byteBuffer 的情况下将这个复杂的对象转换为字符串?

非常感谢任何帮助。

最佳答案

显然,您不想将 ByteBuffer 属性序列化为另一个结构化类,而只是将内容序列化为字符串。一种方法是在方法上使用 @JsonProperty 注释来告诉映射器使用该方法,而不是尝试直接序列化字段。假设你有一个像这样的bean:

class Stuff {

    private ByteBuffer data;

    public Stuff() {
    }

    public Stuff(ByteBuffer data) {
        super();
        this.data = data;
    }

    public ByteBuffer getData() {
        return data;
    }

    public void setData(ByteBuffer data) {
        this.data = data;
    }

    @JsonProperty(value = "data")
    public String convertData() {
        return new String(data.array());
    }

    @JsonProperty("data")
    public void convertData(String s) {
        data = ByteBuffer.wrap(s.getBytes());
    }

}

映射器现在将使用convertData 方法来序列化和反序列化ByteBuffer 数据属性,并且您仍然可以使用普通的java bean 属性方法。

更新:

由于序列化类无法更改,因此这里有一种使用一些高级 JACKSON 内容的替代方法。首先,创建自定义序列化器和反序列化器:

static class ByteBufferSerializer extends JsonSerializer<ByteBuffer> {

    @Override
    public void serialize(ByteBuffer value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        jgen.writeString(new String(value.array()));
    }
}

static class ByteBufferDeserializer extends JsonDeserializer<ByteBuffer> {

    @Override
    public ByteBuffer deserialize(JsonParser jp,
            DeserializationContext context) throws IOException,
            JsonProcessingException {
        return ByteBuffer.wrap(jp.getText().getBytes());
    }

}

然后,创建一个Mixin接口(interface),为我们在真实目标类中无法提供的属性提供注解:

static interface Mixin {

    @JsonSerialize(using = ByteBufferSerializer.class, contentAs = String.class)
    ByteBuffer getData();

    @JsonDeserialize(using = ByteBufferDeserializer.class, contentAs = String.class)
    void setData(ByteBuffer data);

}

此外,创建一个用于配置对象映射器的模块,并添加 mixin 接口(interface):

static class MyModule extends SimpleModule {
    public MyModule() {
        super("ByteBuffer wrangling");
    }

    @Override
    public void setupModule(SetupContext context) {
        context.setMixInAnnotations(Stuff.class, Mixin.class);
    }
}

最后,向映射器注册模块:

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new MyModule());

瞧,小菜一碟! :-)

关于java - ObjectMapper writeValueAsString 更改字节缓冲区 pos,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17291704/

相关文章:

java - 子串方法

java - 遵循 BDD 时单元测试与端到端(集成本身)之间的关系

java - 即使通过java中的测试传递值,属性也为空?

java - hibernate ehcache测试失败

java - 在类型 'httpServletRequest' 的对象上找不到属性或字段 'org.springframework.webflow.engine.impl.RequestControlContextImpl'

java - Spring Boot多部分文件上传集成测试-空文件

java - 在java中使用heapsort进行排序

java - 将 html 设计集成到 servlet

java - 无法让 AdMob 工作(使用 Android、LibGDX)

java - 学习java,为什么我的私处是private?