Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Ich stehe momentan vor einem seltsamen Problem auf das ich keine Lösung finden konnte:
Mittels gson serialisiere und deserialisiere ich eine Klasse (Java -> Java, die gleiche Binary und auch die gleiche Klasse). Nun habe ich in der Klasse einen
Java:
public Object payload;
welches ich vor dem serialisieren setze:
Java:
payload = "Ich bin ein String";
nach dem deserialisieren versuche ich auf den String zuzugreifen:
Java:
String thePayload = (String)payload;
oder
Java:
String thePayload = payload.toString();
Beide Varianten funktionieren nicht. Bei der Ersten bekomme ich den Fehler, dass ein Object nicht zu einem String konvertiert werden kann. Bei der zweiten Variante bekomme ich einen String mit dem Inhalt "java.lang.Object@b9b618".
Was kann ich tun, damit ich den String wiederbekomme?
Mal doof gefragt: Hat es einen bestimmten Grund warum du payload nicht als String deklarierst in deiner java-Klasse? Dann sollte gson da auch etwas vernünftiges draus machen?!
Ja, einen Grund hat es. Ich kommuniziere mit der Klasse zwischen Client und Server und möchte Variabel bleiben, was für Objekte ich übertrage. Das können HashMaps sein, Stacks, Integers, bool, String, was auch immer. Ich möchte nicht für jeden Datentyp ein eigenes Feld haben müssen, darum habe ich hier Object genommen um generisch zu bleiben.
import com.google.gson.annotations.SerializedName;
import java.util.HashMap;
public class Command {
@SerializedName("ID")
private int id;
@SerializedName("Action")
private Action action;
@SerializedName("Params")
private HashMap<Param, Object> params;
public Command()
{
id = Main.Instance().GetNextCmdId();
params = new HashMap<Param, Object>();
}
public int GetId()
{
return id;
}
public void SetParam(Param param, Object value)
{
if (params.containsKey(param))
return;
params.put(param, value);
}
public Action GetAction()
{
return action;
}
public Object GetParam(Param param)
{
if (!params.containsKey(param))
return null;
return params.get(param);
}
public <T> T GetParam(Param param, Class<T> classOfT)
{
return (T)GetParam(param);
}
}
Das payload ist einfach ein Element in params. Ich setze per Command.SetParam(Param.Irgendwas, txtTextFeld.GetText()); einen Wert (als Payload) und serialisiere die Klasse mit gson, schicke sie an den Server oder den Client und deserialisiere sie dort wieder.
Java:
Command.GetParam(Param.Irgendwas, String.class);
gibt mir eben den Fehler, dass ein Object nicht zu einem String gecastet werden kann und
Java:
Command.GetParam(Param.Irgendwas).toString();
gibt mir nicht den gewünschten String sondern eben die Objektinstanz als Namen (java.lang.Object@b9b618).
Senden/Empfangen:
Java:
// Senden
Gson gson = new Gson();
String json = gson.toJson(cmd);
Main.SendOnSocket(clientConnection, json); // Sendet und flusht
// Empfangen
Gson gson = new Gson();
String receive = in.readLine(); // in = BufferedReader des Sockets.
Command cmd = (Command) gson.fromJson(receive, Command.class);
ist es garantiert das richtige Command, stimmt die Id? wird die von dir beliebig vergeben?
verwende erstmal keine komplizierte Map, sondern übertrage einen Test-String in einem String-Attribut, klappt das?
als nächstes ein Object-Attribut, gehts da?
generell solltest du versuchen, Konventionen einzuhalten, Methoden und Variablen klein schreiben!
Genau das hatte ich zuhause auch schon probiert und ich bin auf viele Schwierigkeiten dabei gestoßen. Ich versuche das Momentan so zu lösen:
anstatt [c]Object[/c] nutze ich [c]String[/c]. Warum? Ich lasse mir einfach aus dem "Objekt" ein JSON-String erzeugen und speichere diesen ab. Ist noch unausgereift, aber so ist derzeit meine idee:
Java:
import com.google.gson.Gson;
public class GSONDemo
{
public static Gson GSON = new Gson();
public static void main(String[] args)
{
DClass cl = new DClass("hallo");
String json = GSON.toJson(cl);
System.out.println("JSON: " + json);
DClass rc = GSON.fromJson(json, DClass.class);
String data = (String)rc.getObject();
System.out.println("String-Objekt: " + data);
}
}
class DClass
{
private String value, clazz;
public DClass()
{
}
public DClass(Object obj)
{
value = GSONDemo.GSON.toJson(obj);
clazz = obj.getClass().getName();
}
public String getValue()
{
return value;
}
public String getClazz()
{
return clazz;
}
public Object getObject()
{
try
{
Class cl = Class.forName(clazz);
return GSONDemo.GSON.fromJson(value, cl);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
return null;
}
}
}
Normal brauchst du da nie selbst mit Reflection rummachen, das macht gson schon selbst! Du musst ihm halt nur genau sagen was du machen willst! Am Besten mal den guide durchlesen.
In dem Beispiel von Tomate würde sich evtl. so etwas anbieten ???:L
Java:
class DClass<T> {
private T value;
public DClass() {
}
public DClass(T obj) {
this.value = obj;
}
public T getValue() {
return value;
}
@Override
public String toString() {
return value.toString();
}
}
(Klasse enthält keine zusätzlichen Infos!! ) Dafür erhält gson ein TypeToken!:
Java:
public static void main(String[] args) {
Gson GSON = new Gson();
Type type = new TypeToken<DClass<String>>() {}.getType();
DClass<String> cl = new DClass<String>("hallo");
String json = GSON.toJson(cl, type);
System.out.println("JSON: " + json);
DClass<String> rc = GSON.fromJson(json, type);
System.out.println("value-Objekt: " + rc.getValue());
}
Das ist mein momentaner Workaround, alles in einen String zu tun und ihn dann einfach zu Integers und booleans zu konvertieren. Hier ist aber das Problem, dass ich keine Stacks<> oder HashMaps<> übermitteln kann, weil es auf Strings beschränkt ist. Wenn es ein Objekt wäre könnte ich einfach meine HashMap der params HashMap hinzufügen.
eRaaaa: das wäre eine Lösung, wenn auch im Gegensatz [c]Object[/c] zu verwenden etwas komplexer. Eine Lösung mit Object wäre ideal imo, aber wenn ich keine Lösung finde, werde ich es warscheinlich so machen. Danke!
Das ist mein momentaner Workaround, alles in einen String zu tun und ihn dann einfach zu Integers und booleans zu konvertieren. Hier ist aber das Problem, dass ich keine Stacks<> oder HashMaps<> übermitteln kann, weil es auf Strings beschränkt ist. Wenn es ein Objekt wäre könnte ich einfach meine HashMap der params HashMap hinzufügen.
Sicher das du mich richtig verstanden hast? Ich meinte: Du willst im Objekt etwas unbekanntes speichern, sei es String, Hashmap oder ieine x-Belibige Referenz. Egal. Dieses Objekt lässt du mittels gson in ein json string umwandeln und übergibst diesen. Ich meine nicht, dass du das tun sollst: String.valueOf(Object).
Durch mein gepostetes Beispiel, sollte das eigentl. klar geworden sein :-/