Reputation: 3550
I have to write a proxy client in Java to connect to JSON WebService. I have only textual description of WebService methods and types. For instance the result of one method is
Params { byte[] challenge; byte[] proff; }
If I create a class Params in Java with both fields as byte[], jackson mapper treats them as binary arrays and encodes as following example
{"id":2,"method":"Authenticate","params":["bSwY+kKRO7sIJNZFG/L3dK2ke1kIDwzyK5n717MyBG1pnRhjqSF0kRMAyEqLYKA6VBwujaR8K/wr98+G1Av9vQ12soFi+3DViPN4YDguqF0=","2iNJ5UEK3eVxFTEUHMN04QM8WtNrwGSIu1hKVXFMVvQ="]}
The WebService exptects those parameters in a form of comma separated non negative byte values like
[truncated] {"id":2,"method":"Authenticate","params":[[114,109,104,101,70,88,16,32,102,17,117,3,105,104,112,4,39,103,11,54,90,106,90,69,26,20,5,10,121,52,108,64,106,102,52,124,87,8,21,29,28,119,110,70,122,33,105, ...............
I concluded that Jackson mapper uses some kind of automatic Java type recognition and chooses the corresponding JSON type. Is there a way to control it and ie change the type the serializer should use for particular Java type serialization? Where is description and mapping between Java and JSON types?
Regards
Upvotes: 0
Views: 731
Reputation: 67003
Jackson is representing the byte[] as a base 64 encoded string.
You'll need to implement a custom serializer, to manually iterate through the byte[] and generate the JSON array of integer values.
That didn't work out quite as I expected it should.
import java.io.IOException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.module.SimpleModule;
public class Foo
{
public static void main(String[] args) throws Exception
{
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(new Bar()));
// output: {"bytes":"AQIDBAUGBwgJCgsMDQ4PEA=="}
SimpleModule module = new SimpleModule("byte[] as integers", Version.unknownVersion());
module.addSerializer(byte[].class, new ByteArrayAsIntegersSerializer());
mapper = new ObjectMapper().withModule(module);
System.out.println(mapper.writeValueAsString(new Bar()));
// output: {"bytes":"AQIDBAUGBwgJCgsMDQ4PEA=="}
// ByteArrayAsIntegersSerializer was not used!
module = new SimpleModule("byte[] as integers 2", Version.unknownVersion());
module.addSerializer(Bar.class, new BarSerializer());
mapper = new ObjectMapper().withModule(module);
System.out.println(mapper.writeValueAsString(new Bar()));
// output: {"bytes":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]}
}
}
class Bar
{
public byte[] bytes = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
}
class BarSerializer extends JsonSerializer<Bar>
{
@Override
public void serialize(Bar value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeStartObject();
jgen.writeFieldName("bytes");
jgen.writeStartArray();
for (byte b : value.bytes)
jgen.writeNumber(b);
jgen.writeEndArray();
jgen.writeEndObject();
}
}
class ByteArrayAsIntegersSerializer extends JsonSerializer<byte[]>
{
@Override
public void serialize(byte[] bytes, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
jgen.writeStartArray();
for (byte b : bytes)
jgen.writeNumber(b);
jgen.writeEndArray();
}
}
Upvotes: 1