How to get additional fields in a json data in GSON
I have a JSON object which is actually a java object serialized. The JSON object is something like this
{
user: 'user',
telephone: '123456789'
}
The java object's telephone field was renamed from 'telephone' to 'mobile'. So now the java object is has following fields.
- user
- mobile
What i want to do is a data migration. I want to get the data from the database as a JSON string -> and parse that JSON to java object using GSON (So far we are used gson.fromJson(class, data) method) preserving the value in the telephone (since telephone is not a field in the java class now) - so then i can pass that data to the new field (mobile).
How can i do this?
P.S. :- This cannot achieve by some simple database query because we are using a file storage system which don't have query facility and encoded values.
P.S. :- Also, we are using the entity event framework
You need to write custom deserialiser and map telephone
to mobile
:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.annotations.JsonAdapter;
import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Type;
public class GsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
Gson gson = new GsonBuilder()
.create();
try (FileReader jsonReader = new FileReader(jsonFile)) {
System.out.println(gson.fromJson(jsonReader, User.class));
}
}
}
class UserJsonDeserializer implements JsonDeserializer<User> {
@Override
public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
User user = new User();
user.setUser(jsonObject.get("user").getAsString());
user.setMobile(jsonObject.get("telephone").getAsString());
return user;
}
}
@JsonAdapter(UserJsonDeserializer.class)
class User {
private String user;
private String mobile;
// getters, setters, toString
}
Prints:
User{user='user', mobile='123456789'}
In case another google wanderer finds this question, there is a way to process extra tags without completely recreating the de-serialization. Based on an example given here. The basic premise is this factory gets the first go at deserializing the class, it uses the next possible type adapter for the class to handle the initial deserialize, does its post processing and returns the result.
class UserTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
if (!User.class.isAssignableFrom(type.getRawType())) return null; // this class only serializes 'User' and its subtypes
final TypeAdapter<User> userAdapter = gson.getDelegateAdapter(this, TypeToken.get(User.class)); // next adapter that isn't this one
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
TypeAdapter<User> result = new TypeAdapter<User>() {
public void write(JsonWriter out, User value) throws IOException {
userAdapter.write(out, value);
}
public User read(JsonReader in) throws IOException {
JsonObject object = elementAdapter.read(in).getAsJsonObject();
User profile = userAdapter.fromJsonTree(object);
// apply old field to the new, if found (or whatever other post processing)
try { profile.mobile = object.get("telephone").getAsString(); }
catch (Exception ignored) {}
return profile;
}
}.nullSafe();
return (TypeAdapter<T>) result;
}
}
Then you add to your Gson object something like this and use as normal
private Gson createGson() {
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapterFactory(new UserTypeAdapterFactory());
return gsonBuilder.create();
}
Note in this case JsonReader/JsonWriter are from gson library, there may be other implementations, so mind the imports.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;