Столкнулся с непонятной проблемой в JBoss и RESTEasy:
Когда сервис принимает или отдаёт данные в JSON формате Jackson (сериализатор/десериализатор JSON) игнорирует JAXB аннотации @XmlElement(name = "bla_bla")
вместо указанного имя поля всегда используется имя поля в классе, т.е. такое:
@XmlRootElement
class SimpleJson
{
@XmlElement(name = "my_name")
public String megaName;
}
сериализуется в это:
{
"megaName" : ""
}
а не, как ожидается, в это:
{
"my_name" : ""
}
А так же игнорируется @XmlJavaTypeAdapter
, что есть пичалька.
Тут по ходу сочинения заметки пришло в голову, что Джексон не настроен использовать JaxbAnnotationIntrospector
- повод рассмотреть.
Пока же использую work-around, в виде дополнительного навешивания Jackson-аннотаций вроде:
@XmlRootElement
class SimpleJson
{
@XmlElement(name = "my_name")
@XmlJavaTypeAdapter(Iso8601DateAdapter.class)
@JsonProperty(value = "my_name")
@JsonSerialize(using = JsonIso8601DateSeializer.class)
@JsonDeserialize(using = JsonIso8601DateDeserializer.class)
public Date megaName;
}
Подкатом, бонусом, классы Iso8601DateAdapter
, JsonIso8601DateSeializer
, JsonIso8601DateDeserializer
.
package net.homelinux.hatred.ws.common.data;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Iso8601DateAdapter extends XmlAdapter<String, Date>
{
// Logger
private static final Logger log = LoggerFactory.getLogger(Iso8601DateAdapter.class);
private final static DateFormat _df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
@Override
public String marshal(Date date)
{
String result = null;
try
{
result = _df.format(date);
// Add ':' to TZ
result = result.substring(0, 22) + ":" + result.substring(22, result.length());
log.info("Convert date to string: {}", result);
}
catch (Exception e)
{
log.error("Could not date to string '{}'", date.toString());
}
return result;
}
@Override
public Date unmarshal(String string)
{
Date result = null;
try
{
// Strip ':' from TZ
string = string.substring(0, 22) + string.substring(23, string.length());
result = _df.parse(string);
log.info("Convert string to date: {}", result);
}
catch (Exception e)
{
log.error(String.format("Could not parse date string '%s'", string));
}
return result;
}
}
package net.homelinux.hatred.ws.common.data;
import java.io.IOException;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
/**
* Jackson ISO8601 date serializer
*
* @author Alexander 'hatred' Drozdov
* <p/>
* Date: 20.03.12
* Time: 15:15
*/
public class JsonIso8601DateSeializer extends JsonSerializer<Date>
{
// Reuse exists adapter for JaxB
private static final Iso8601DateAdapter adapter = new Iso8601DateAdapter();
@Override
public void serialize(Date date,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)
throws IOException, JsonProcessingException
{
String serialized = adapter.marshal(date);
jsonGenerator.writeString(serialized);
}
}
package net.homelinux.hatred.ws.common.data;
import java.io.IOException;
import java.util.Date;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
/**
* Jackson ISO8601 date deserializer
*
* @author Alexander 'hatred' Drozdov
* <p/>
* Date: 20.03.12
* Time: 15:21
*/
public class JsonIso8601DateDeserializer extends JsonDeserializer<Date>
{
// Reuse exists adapter for JaxB
private static final Iso8601DateAdapter adapter = new Iso8601DateAdapter();
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException
{
String dateString = jsonParser.getText();
Date deserialized = adapter.unmarshal(dateString);
return deserialized;
}
}