GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Alguém consegue me dar um exemplo de serialização com Gson que funcione?

java
Tags: #<Tag:0x00007f2421a97620>

#1

Olá. Eu tentei serializar um objeto recentemente, porém dentro do mesmo existem várias StringProperty, e as mesmas não são serializáveis. Então eu descobri que é possível serializar com Gson, porém eu estou a dois dias testando exemplos na internet todos dão em exceções diferentes. Alguém pode me dar um exemplo? Eu tenho somente uma classe User com várias StringProperty e quero salvar em um .json.


#2

Um palpite maroto: Não seria melhor desacoplar tua camada de negócio (ou de modelo) da camada de UI?

Pelo que eu vi aqui, a StringProperty é uma classe do JavaFX, correto? Acredito que se você precisa serializar a entidade, provavelmente é uma entidade do negócio independente da UI.

Se você fizer essa separação, vai ficar simples serializar o POJO. Agora, pode também ser o caso de você precisar utilizar as funcionalidades da StringProperty de alguma forma amarrada com os outros dados do POJO.

Se realmente você não pode realizar a separação, você sabe como é que o GSON serializa teus objetos? Se tiver como configurar ele para utilizar os GETTERS ao invés da propriedades em si, você pode também fazer algo como:

public String getStringProperty() {
    String foo = ...; // Transforma a StringProperty em String
    return foo;
}

Dessa forma, na hora de remontar o objeto, você pode fazer o processo contrário para transformar a String em StringProperty.

Obs: alguns chamam isso de gambiarra, mas podemos chamar de recurso técnico.


#3

Acredito que um exemplo real do que você precisa seria melhor !!! Poderia então colocar um código ou um exemplo aproximado da sua duvida?


#4

Não, eu não posso separar o model da view porque existem vários binds com o objeto User.


#5

Entendi. Tenta fazer a questão do getter/setter para serializar como String então, caso não encontre como serializar o StringProperty mesmo.


#6

Nesse post do StackOverflow, o cara disse que conseguiu fazer um esquema com um LinkedHashMap. Já tentou algo assim?


#7

Eu não postei o código por dois motivos, primeiro, não achei necessário pois eu quero somente serializar um objetos com atributos Property, nada mais, e segundo, minha classe User tá toda bagunçada porque eu fiquei fazendo testes que não deram certo, mas se é necessário mesmo, eu coloco aqui:

Classe User

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedHashMap;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class User implements JsonSerializer<User> {

	private StringProperty Name = new SimpleStringProperty();
	private StringProperty Email = new SimpleStringProperty();
	private BooleanProperty Gender = new SimpleBooleanProperty();
	private StringProperty Picture = new SimpleStringProperty();
	private StringProperty googleId = new SimpleStringProperty();

	private ArrayList<String> Likes = new ArrayList<String>();
	private ArrayList<Event> Events = new ArrayList<Event>();

	public User(String googleId2, String n, String em, boolean g, String p, ArrayList<String> l) {
		this.Name.set(formatName(n));
		this.Email.set(em);
		this.Gender.set(g);
		this.Picture.set(p);
		this.Likes = l;
		this.googleId.set(googleId2);;
	}
	
	public User(){
		
	}
	
	private String formatName(String n){
		n = n.replaceFirst(" ", "");
		String r = "";
		String[] split = n.split(" ");
		for(String str : split){
			str = str.substring(0,1).toUpperCase().concat(str.substring(1));
			r+=str;
		}
		return r;
	}

	public final StringProperty NameProperty() {
		return this.Name;
	}
	

	public final String getName() {
		return this.NameProperty().get();
	}
	

	public final void setName(final String Name) {
		this.NameProperty().set(Name);
	}
	

	public final StringProperty emailProperty() {
		return this.Email;
	}
	

	public final String getEmail() {
		return this.emailProperty().get();
	}
	

	public final void setEmail(final String email) {
		this.emailProperty().set(email);
	}
	

	public final BooleanProperty GenderProperty() {
		return this.Gender;
	}
	

	public final boolean isGender() {
		return this.GenderProperty().get();
	}
	

	public final void setGender(final boolean Gender) {
		this.GenderProperty().set(Gender);
	}
	

	public final StringProperty PictureProperty() {
		return this.Picture;
	}
	

	public final String getPicture() {
		return this.PictureProperty().get();
	}
	

	public final void setPicture(final String Picture) {
		this.PictureProperty().set(Picture);
	}
	
	public ArrayList<String> getLikes() {
		return Likes;
	}

	public void setLikes(ArrayList<String> likes) {
		Likes = likes;
	}

	public ArrayList<Event> getEvents() {
		return Events;
	}

	public void setEvents(ArrayList<Event> events) {
		this.Events = events;
	}

	@Override
	public JsonElement serialize(User u, Type t, JsonSerializationContext j) {
        JsonObject result = new JsonObject();
        result.add("googleid", new JsonPrimitive(u.googleId.get()));
        result.add("name", new JsonPrimitive(u.NameProperty().get()));
        result.add("email", new JsonPrimitive(u.emailProperty().get()));
        result.add("gender", new JsonPrimitive(u.GenderProperty().get()));
        result.add("picture", new JsonPrimitive(u.PictureProperty().get()));
        return result;
	}
	
	public LinkedHashMap<String, Object> getUserData() {
	    LinkedHashMap<String, Object> userData = new LinkedHashMap<>();

	    userData.put("googleid", googleIdProperty().getValue());
	    userData.put("name", NameProperty().getValue());
	    userData.put("email", emailProperty().getValue());
	    userData.put("gender", GenderProperty().getValue());
	    userData.put("picture", PictureProperty().getValue());
	    return userData;
	}

	public final StringProperty googleIdProperty() {
		return this.googleId;
	}
	

	public final String getGoogleId() {
		return this.googleIdProperty().get();
	}
	

	public final void setGoogleId(final String googleId) {
		this.googleIdProperty().set(googleId);
	}	
}

Então na hora de escrever eu faço isso:

com.google.gson.Gson gson = new GsonBuilder().create();
Writer.WriteJSONObject(gson.toJson(currentUser), Methods.MakeProgramFolder().getAbsolutePath()+"/user.json");

Obs: MakeProgramFolder retorna um objeto File e o objeto currentUser é um objeto User

Writer.WriteJSONObject:

	public static boolean WriteJSONObject(String obj, String file){
	FileOutputStream FOS;
	try {
		FOS = new FileOutputStream(file);
		FOS.write(obj.getBytes());
		FOS.flush();
		FOS.close();
	} catch (IOException e) {
		e.printStackTrace();
		return false;
	}
	return true;
}

E para ler eu faço assim:

Gson gsonParser = new Gson();
Map<String, User> gsonResponse; // You don't need to do new here
Type collectionType = new TypeToken<Map<String, User>>() {}.getType();
gsonResponse = gsonParser.fromJson(Writer.ReadObject(new File(Methods.MakeProgramFolder().getAbsoluteFile()+"/user.json")), collectionType);

Writer.ReadObject

	public static String ReadObject(File file) throws IOException, ClassNotFoundException{
	return new String(Files.readAllBytes(file.toPath()));
}

#8

E eu estou recebendo a seguinte exceção:

    Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 398 path $.
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:224)
	at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:187)
	at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
	at com.google.gson.Gson.fromJson(Gson.java:887)
	at com.google.gson.Gson.fromJson(Gson.java:852)
	at com.google.gson.Gson.fromJson(Gson.java:801)
	at com.tkfentreteniment.meusdados.start.Start.main(Start.java:31)
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 398 path $.
	at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:213)
	... 7 more

#9

E o user.json ficou todo zoado:

{"Name":{"name":"","value":"ThallyssonKlein","valid":false},"Email":{"name":"","value":" thallyssonklein@gmail.com","valid":false},"Gender":{"name":"","value":false,"valid":true},"Picture":{"name":"","value":" https://lh5.googleusercontent.com/-R5JjRw7ocHs/AAAAAAAAAAI/AAAAAAAAIV8/jmrc9URk6fM/photo.jpg","valid":false},"googleId":{"name":"","value":"117892930171106636776","valid":true},"Events":[]}


#10

Na realidade, se fosse possível a serialização normal mesmo com as Properties, eu prefiro, porém se não for possível, eu só quero gerar um .json com os atributos da classe User.


#11

É muito simples serializar usando Gson.

import com.google.gson.Gson;

String mensagem = null;
User user = new User();
user.setName(“Douglas”);
user.setEndereco(“Rua tal, 123123”);

Gson gson = new Gson();
mensagem = gson.toJson(user);
System.out.println(mensagem);


#12

E pra desserializar?


#13

import com.google.gson.Gson;

//body é array de byte da mensagem
String message = new String(body, “UTF-8”);
Gson gson = new Gson();
Position position = gson.fromJson(message, Position.class);
System.out.println(message);


#14

Eu salvei assim:

String json = null;
Gson gson = new Gson();
json = gson.toJson(currentUser);
System.out.println(json);
File fJson = new File(Methods.MakeProgramFolder().getAbsolutePath()+"/user.json");
if(!fJson.exists()){fJson.createNewFile();}
    BufferedWriter buffWrite = new BufferedWriter(new FileWriter(fJson));
buffWrite.append(json);
    buffWrite.close();

E estou lendo assim:

File fJson = new File(Methods.MakeProgramFolder().getAbsolutePath()+"/user.json");
if(!fJson.exists()){fJson.createNewFile();}
BufferedReader br = new BufferedReader(new FileReader(fJson));
String line;
String json = "";
while((line = br.readLine()) !=null){
    json+=line;
}
String u = new String(json.getBytes(), "UTF-8");
Gson gson = new Gson();
User user = gson.fromJson(u, User.class);
System.out.println(u);
//UserDAO.signInOffline(user);

E estou recebendo esta exceção:

Exception in thread "main" java.lang.RuntimeException: Failed to invoke public javafx.beans.property.StringProperty() with no args
	at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:111)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:210)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:129)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:220)
	at com.google.gson.Gson.fromJson(Gson.java:887)
	at com.google.gson.Gson.fromJson(Gson.java:852)
	at com.google.gson.Gson.fromJson(Gson.java:801)
	at com.google.gson.Gson.fromJson(Gson.java:773)
	at com.tkfentreteniment.meusdados.start.Start.main(Start.java:36)
Caused by: java.lang.InstantiationException
	at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.google.gson.internal.ConstructorConstructor$3.construct(ConstructorConstructor.java:108)
	... 8 more

#15

Ele está com problema na escrita ou leitura?
O que tem nessa linha?

at com.tkfentreteniment.meusdados.start.Start.main(Start.java:36)


#16

User user = gson.fromJson(u, User.class);


#17

Se for bindings javafx que está falando, talvez você deveria renomear o objeto User para UserView.


#18

Ele está gerando o json?
Leitura e escrita são projetos diferentes? Estão em pastas diferentes?


#19

A leitura e a escrita eu realizo a partir de classes diferentes. O caminho está correto, e o .json fica assim:

{"Name":{"name":"","value":"ThallyssonKlein","valid":false},"Email":{"name":"","value":" thallyssonklein@gmail.com","valid":false},"Gender":{"name":"","value":false,"valid":true},"Picture":{"name":"","value":" https://lh5.googleusercontent.com/-R5JjRw7ocHs/AAAAAAAAAAI/AAAAAAAAIV8/jmrc9URk6fM/photo.jpg","valid":false},"googleId":{"name":"","value":"117892930171106636776","valid":true},"Events":[]}

#20

As classes precisam ser idênticas