Created
September 27, 2017 07:30
-
-
Save alexcmd/367a61d21e112343c5d5da64765cce05 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Console out | |
// [{"op":"replace","path":"/b/name","value":"name2"},{"op":"replace","path":"/b/price","value":2.0}] | |
// Change B | |
// name string | |
// Change name to name2 | |
// price float | |
// Change price to 2.0 | |
// {"b":{"name":"name2","price":2.0},"id":0} | |
// ====================================================== | |
import com.alibaba.fastjson.JSON; | |
import com.fasterxml.jackson.databind.JsonNode; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.flipkart.zjsonpatch.JsonDiff; | |
import java.io.IOException; | |
import java.lang.reflect.InvocationTargetException; | |
public class App { | |
public static void main(String[] args) throws IOException { | |
ObjectMapper mapper = new ObjectMapper(); | |
ObjB b = new ObjB(); | |
b.setName("name1"); | |
b.setPrice(1.0f); | |
ObjA a = new ObjA(); | |
a.setId(10); | |
a.setB(b); | |
String json = JSON.toJSONString(a); | |
JsonNode node1 = mapper.readTree(json); | |
b.setPrice(2.0f); | |
b.setName("name2"); | |
String json2 = JSON.toJSONString(a); | |
JsonNode node2 = mapper.readTree(json2); | |
JsonNode diff = JsonDiff.asJson(node1, node2); | |
try { | |
ObjectPatch.apply(new ObjA(),diff.toString()); | |
} catch (InvocationTargetException e) { | |
e.printStackTrace(); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} catch (InstantiationException e) { | |
e.printStackTrace(); | |
} | |
//System.out.println(diff.toString()); | |
} | |
} | |
// ====================================================== | |
import com.alibaba.fastjson.JSON; | |
import com.fasterxml.jackson.databind.JsonNode; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.sun.xml.internal.ws.util.StringUtils; | |
import java.io.Console; | |
import java.io.IOException; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.Arrays; | |
import java.util.Iterator; | |
import java.util.Objects; | |
import java.util.Optional; | |
import java.util.stream.Stream; | |
public class ObjectPatch { | |
public static <T> void apply(T object, String jsonPatch) throws IOException, InvocationTargetException, IllegalAccessException, InstantiationException { | |
System.out.println(jsonPatch); | |
ObjectMapper mapper = new ObjectMapper(); | |
JsonNode node = mapper.readTree(jsonPatch); | |
for (Iterator<JsonNode> it = node.elements(); it.hasNext(); ) { | |
Object currentObject = object; | |
JsonNode elm = it.next(); | |
String operation = elm.get("path").asText(); | |
String[] path = elm.get("path").asText().split("/"); | |
JsonNode value = elm.get("value"); | |
Class<?> currentType = object.getClass(); | |
for (int i = 1; i < path.length; i++) { | |
String pathPart = path[i]; | |
Optional<Field> field = Arrays.stream(currentType.getDeclaredFields()).filter(f -> f.getName().equalsIgnoreCase(pathPart)).findFirst(); | |
if (!field.isPresent()) | |
break; | |
String setMethodName = "set" + pathPart; | |
String getMethodName = "get" + pathPart; | |
Optional<Method> getMethod = null; | |
if (i<path.length-1) { | |
getMethod = Arrays.stream(currentType.getMethods()).filter(method1 -> method1.getName().equalsIgnoreCase(getMethodName)).findFirst(); | |
Object newObj = getMethod.get().invoke(currentObject); | |
Optional<Method> setMethod = Arrays.stream(currentType.getMethods()).filter(method1 -> method1.getName().equalsIgnoreCase(setMethodName)).findFirst(); | |
if (newObj == null) { | |
newObj = getMethod.get().getReturnType().getConstructors()[0].newInstance(); | |
setMethod.get().invoke(currentObject,newObj); | |
} | |
currentType = field.get().getType(); | |
currentObject = newObj; | |
continue; | |
} | |
Class<?> fieldType = field.get().getType(); | |
Stream<Method> m = Arrays.stream(currentType.getMethods()); | |
Optional<Method> setMethod = Arrays.stream(currentType.getMethods()).filter(method1 -> method1.getName().equalsIgnoreCase(setMethodName)).findFirst(); | |
Object new_val=null; | |
switch (fieldType.getName()) | |
{ | |
case "float": | |
System.out.println(pathPart+" float"); | |
new_val = ((float) value.asDouble()); | |
break; | |
case "java.lang.String": | |
System.out.println(pathPart+" string"); | |
new_val = value.asText(); | |
break; | |
default: | |
break; | |
} | |
setMethod.get().invoke(currentObject,new_val); | |
} | |
} | |
System.out.println(JSON.toJSONString(object)); | |
} | |
} | |
// ====================================================== | |
public class ObjA { | |
private int id; | |
private ObjB b; | |
public int getId() { | |
return id; | |
} | |
public void setId(int id) { | |
this.id = id; | |
} | |
public ObjB getB() { | |
return b; | |
} | |
public void setB(ObjB b) { | |
System.out.println("Change B"); | |
this.b = b; | |
} | |
} | |
// ====================================================== | |
public class ObjB { | |
private String name; | |
private float price; | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
System.out.println("Change name to " +name); | |
this.name = name; | |
} | |
public float getPrice() { | |
return price; | |
} | |
public void setPrice(float price) { | |
System.out.println("Change price to " +price); | |
this.price = price; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment