package com.ppdai.das.client.sqlbuilder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializer; import com.ppdai.das.client.BatchUpdateBuilder; import com.ppdai.das.client.Segment; import com.ppdai.das.client.SqlBuilder; import com.ppdai.das.core.DasDiagnose; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Supplier; public class SqlBuilderSerializer implements Serializer { private SerializeFactory serializeFactory = SerializeFactory.getInstance(); public final static SqlBuilderSerializer instance = new SqlBuilderSerializer(); SqlBuilderSerializer(){ serializeFactory.addAll(ExpressionSerializers.expressionSerializers()); serializeFactory.addAll(TextSerializers.textSerializers()); serializeFactory.add(new ColumnDefinitionSerializer()); serializeFactory.add(new ColumnOrderSerializer()); serializeFactory.add(new ColumnReferenceSerializer()); serializeFactory.add(new TableDeclarationSerializer()); serializeFactory.add(new TableDefinitionSerializer()); serializeFactory.add(new TableSerializer()); serializeFactory.add(new TemplateSerializer()); serializeFactory.add(new PageSerializer()); serializeFactory.add(new ParameterSerializer()); serializeFactory.add(new ParameterDefinitionSerializer()); serializeFactory.add(new BatchUpdateBuilderSerializer()); serializeFactory.add(this); } public static String serializeSegment(SqlBuilder segment) { return instance.outGson.toJson(segment); } public static SqlBuilder deserializeSegment(String json) { return instance.outGson.fromJson(json, SqlBuilder.class); } public static String serializeBatchUpdateBuilder(BatchUpdateBuilder segment) { return instance.outGson.toJson(segment); } public static BatchUpdateBuilder deserializeBatchUpdateBuilder(String json) { return instance.outGson.fromJson(json, BatchUpdateBuilder.class); } public static String serializePrimitive(Object primitive) { return instance.primitiveGson.toJson(primitive); } public static <T> T deserializePrimitive(String json) { if(json == null) { return null; } return (T) instance.primitiveGson.fromJson(json, Supplier.class).get(); } @Override public Segment deserialize(JsonObject jo) { SqlBuilder sqlBuilder = new SqlBuilder(); JsonArray segs = jo.get("segments").getAsJsonArray(); for(JsonElement seg: segs){ sqlBuilder.getSegments().add(getSerializeFactory().deserialize(seg)); } boolean selectCount = ((JsonObject)jo).getAsJsonPrimitive("selectCount").getAsBoolean(); writeField(sqlBuilder, "selectCount", selectCount); return sqlBuilder; } @Override public JsonObject serialize(Segment obj) { SqlBuilder sqlBuilder = (SqlBuilder) obj; JsonObject root = new JsonObject(); JsonArray segs = new JsonArray(); sqlBuilder.getSegments().forEach(seg-> segs.add(getSerializeFactory().serialize(seg, seg.getClass()))); root.add("segments", segs); root.addProperty("selectCount", sqlBuilder.isSelectCount()); return addBuildType(root); } @Override public Class getBuildType() { return SqlBuilder.class; } final Gson outGson = new GsonBuilder() .registerTypeHierarchyAdapter(Segment.class, (JsonSerializer<Segment>) (segment, typeOfSrc, context) -> serializeFactory.serialize(segment, typeOfSrc)) .registerTypeHierarchyAdapter(Segment.class, (JsonDeserializer<Segment>) (json, typeOfT, context) -> serializeFactory.deserialize(json)) .serializeNulls() .excludeFieldsWithoutExposeAnnotation() .setPrettyPrinting() .create(); final Gson primitiveGson = new GsonBuilder() .registerTypeHierarchyAdapter(DasDiagnose.class, (JsonSerializer<DasDiagnose>) (str, typeOfSrc, context) -> { return JsonNull.INSTANCE; }) .registerTypeHierarchyAdapter(String.class, (JsonSerializer<String>) (str, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", String.class.getSimpleName()); root.add("value", new JsonPrimitive(str)); return root; }) .registerTypeHierarchyAdapter(Long.class, (JsonSerializer<Long>) (l, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", Long.class.getSimpleName()); root.add("value", new JsonPrimitive(l)); return root; }) .registerTypeHierarchyAdapter(Integer.class, (JsonSerializer<Integer>) (l, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", Integer.class.getSimpleName()); root.add("value", new JsonPrimitive(l)); return root; }) .registerTypeHierarchyAdapter(Boolean.class, (JsonSerializer<Boolean>) (l, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", Boolean.class.getSimpleName()); root.add("value", new JsonPrimitive(l)); return root; }) .registerTypeHierarchyAdapter(Float.class, (JsonSerializer<Float>) (f, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", Float.class.getSimpleName()); root.add("value", new JsonPrimitive(f)); return root; }) .registerTypeHierarchyAdapter(Date.class, (JsonSerializer<Date>) (l, typeOfSrc, context) -> { JsonObject root = new JsonObject(); root.addProperty("type", typeOfSrc.getTypeName()); root.add("value", new JsonPrimitive(l.getTime())); return root; }) .registerTypeHierarchyAdapter(Supplier.class, (JsonDeserializer<Supplier>) (json, typeOfT, context) -> { if(json instanceof JsonArray) { JsonArray array = (JsonArray)json; List<Object> list = new ArrayList<>(); for(JsonElement e : array){ list.add(toPrimitive((JsonObject)e).get()); } return () -> list; } return toPrimitive((JsonObject)json); }) .registerTypeHierarchyAdapter(Map.class, (JsonDeserializer<Map>) (json, typeOfT, context) -> { LinkedHashMap<String, Object> map = new LinkedHashMap(); ((JsonObject)json).entrySet().forEach(e->{ map.put(e.getKey(), toPrimitive((JsonObject)e.getValue()).get()); }); return map; }) .create(); Supplier toPrimitive(JsonObject obj){ if(!obj.has("type")){ return ()-> new Object(); } String type = obj.get("type").getAsString(); JsonElement primitive = obj.get("value"); if(type.equals(String.class.getSimpleName())){ return () -> primitive.getAsString(); } if(type.equals(Long.class.getSimpleName())){ return () -> primitive.getAsLong(); } if(type.equals(Integer.class.getSimpleName())){ return () -> primitive.getAsInt(); } if(type.equals(Boolean.class.getSimpleName())){ return () -> primitive.getAsBoolean(); } if(type.equals(Float.class.getSimpleName())){ return () -> primitive.getAsFloat(); } if(type.equals(Date.class.getName())){ return () -> new Date(primitive.getAsLong()); } if(type.equals(Timestamp.class.getName())){ return () -> new Timestamp(primitive.getAsLong()); } return () -> null; } }