#java #json #gson
Написал собственный конвертер, зарегистрировал в GsonBuilder'е. Но отрабатывает только
сериализатор и только в одном "rest-методе".
То есть, он работает, но работает сериализация и десериализация по умолчанию, а мой
конвертер работает только при сериализации одного метода, когда получаю список объектов,
в остальных случаях игнорируется. В логах ошибок нет, тихо и не правильно работает,
не знаю уже что делать. Сталкивался ли кто-нибудь с таким, что не так идет?
Наверно это лишнее, но всё же распишу подробнее.
Провайдер для gson'а.
Класс GsonJsonProvider.java
@Provider
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public class GsonJsonProvider implements MessageBodyReader, MessageBodyWriter{
//---
//инициализация gson и его настроек
private Gson getGson(){
if (gson == null) {
gson = new GsonBuilder()
.registerTypeAdapter(UUID.class, new UUIDConverter())
.registerTypeAdapter(LocalDateTime.class, new DateTimeConverter())
.registerTypeAdapter(Note.class, new NoteConverter())
.setPrettyPrinting()
.serializeNulls()
.setLenient()
.create();
System.err.println("Gson Initialization");
}
System.err.println("Gson work");
return gson;
}
//---
//метод getGson вызывается в этих методах и больше нигде
public Object readFrom(Class type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
InputStreamReader streamReader = new InputStreamReader(entityStream, UTF_8);
try {
Type jsonType;
if (type.equals(genericType)) {
jsonType = type;
} else {
jsonType = genericType;
}
return getGson().fromJson(streamReader, jsonType);
} finally {
streamReader.close();
}
}
//----
public void writeTo(Object object, Class type, Type genericType, Annotation[]
annotations, MediaType mediaType, MultivaluedMap httpHeaders, OutputStream
entityStream) throws IOException, WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
Type jsonType;
if (type.equals(genericType)) {
jsonType = type;
} else {
jsonType = genericType;
}
getGson().toJson(object, jsonType, writer);
} finally {
writer.close();
}
}
Класс модель Note.java
@Entity
@Table(name = "notes")
@NamedQuery(name = "Note.getAll", query = "SELECT n FROM Note n ORDER BY n.id ASC")
public class Note extends Model{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_post")
private int id;
@Type(type = "org.hibernate.type.PostgresUUIDType")
private UUID uuid;
private String title;
private String text;
private String password;
private LocalDateTime date;
private int status;
//---
Класс конвертер NoteConverter.java
@Override
public JsonElement serialize(Note note, Type type, JsonSerializationContext context) {
JsonObject result = new JsonObject();
result.add("uuid", context.serialize(note.getUuid()));
result.addProperty("title", note.getTitle());
result.addProperty("text", note.getText());
result.addProperty("password", note.getPassword() != null ? note.getPassword()
: "null_password");
result.add("date", context.serialize(note.getDate()));
result.addProperty("status", note.getStatus());
return result;
}
и
@Override
public Note deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext
context) throws JsonParseException {
JsonObject jsonObject = jsonElement.getAsJsonObject();
Note note = new Note();
note.setUuid(context.deserialize(jsonObject.get("uuid"), UUID.class));
note.setTitle(jsonObject.get("title").getAsString());
note.setText(jsonObject.get("text").getAsString());
note.setPassword(jsonObject.get("password").getAsString());
note.setDate(context.deserialize(jsonObject.get("date"), LocalDateTime.class));
note.setStatus(jsonObject.get("status").getAsInt());
return note;
}
Класс NoteResource.java
//вот здесь мой сериализатор отрабатывает,
//отдаёт список объектов, где поле date в миллисекундах.
//в логах светится "Gson work" тот, что в GsonJsonProvider.java
@GET
@Produces("application/json; charset=UTF-8")
public Response getAll(){
List noteList = dao.getAll("Note.getAll", noteClass);
return Response.ok(noteList).build();
}
//а здесь, работает сериализация по умолчанию
//и в логах "Gson work" не выходит, то есть он вообще не при делах, почему???
@GET
@Path("/{id}")
@Produces("application/json; charset=UTF-8")
public Response getNote(@PathParam("id") int id){
Note note = dao.getById(id, noteClass);
return Response.ok(note).build();
}
//и здесь тоже самое, сам объект note приходит
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response addNote(Note note){
StatusResponse response = new StatusResponse();
if (note == null) { //эту проверку проходит
System.err.println("Added, note null!");
return Response.status(Response.Status.BAD_REQUEST).entity(response).build();
}
System.err.println("Added, note title: " + note.getTitle());
System.err.println("Added, uuid: " + note.getUuid());
//а здесь uuid = null, так как не знает как десериализовывать тип UUID
//------
UPDATE
Добавил параметризацию в класс GsonJsonProvider.java
public class GsonJsonProvider implements MessageBodyReader, MessageBodyWriter {
//...
Метод readFrom
public T readFrom(Class type, Type genericType, Annotation[] annotations, MediaType
mediaType, MultivaluedMap httpHeaders, InputStream entityStream) throws
IOException, WebApplicationException {
InputStreamReader streamReader = new InputStreamReader(entityStream, UTF_8);
try {
//с genericType так же не работает
return getGson().fromJson(streamReader, type);
} finally {
streamReader.close();
}
}
Метод writeTo
public void writeTo(T t, Class type, Type genericType, Annotation[] annotations,
MediaType mediaType, MultivaluedMap httpHeaders, OutputStream entityStream)
throws IOException, WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
//если указывать type вместо genericType, то не работает
getGson().toJson(t, genericType, writer);
} finally {
writer.close();
}
}
//Сериализация работает как надо, только
//если изменить сеттер в модели Note.java
//но тогда вылетает ошибка при десериализации
//java.lang.ClassCastException: java.util.UUID cannot be cast to java.lang.String
public void setUuid(String uuidString) {
this.uuid = UUID.fromString(uuidString);
}
//а с таким(нормальным) сеттером
//и сер/десериализация не работает (без ошибок в логах)
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
Ответы
Ответ 1 У вас проблема в куске:
if (type.equals(genericType)) {
jsonType = type;
} else {
jsonType = genericType;
}
У вас на выходе тип всегда будет genericType, то есть адаптер никогда не вызовется,
поскольку вы всегда вызываете Gson с дженерик типом.
Комментариев нет:
Отправить комментарий