bạn có thể chuyển đổi này
{ "id":1, "name":"Jack", "parent.id":2 }
vào này
{ "id":1, "name":"Jack", "parent": { "id":2 } }
bằng cách sử dụng
này
// I'm using jQuery here
$.fn.serializeObject = function() {
var arrayData, objectData;
arrayData = this.serializeArray();
objectData = {};
$.each(arrayData, function() {
var value;
if (this.value != null) {
value = this.value;
} else {
value = '';
}
// search for "parent.id" like attribute
if (this.name.indexOf('.') != -1) {
var attrs = this.name.split('.');
var tx = objectData;
for (var i = 0; i < attrs.length - 1; i++) {
if (objectData[attrs[i]] == undefined)
objectData[attrs[i]] = {};
tx = objectData[attrs[i]];
}
tx[attrs[attrs.length - 1]] = value;
} else {
if (objectData[this.name] != null) {
if (!objectData[this.name].push) {
objectData[this.name] = [objectData[this.name]];
}
objectData[this.name].push(value);
} else {
objectData[this.name] = value;
}
}
});
return objectData;
};
và sau đó bạn có thể tuần tự hóa mã của mình bằng cách sử dụng JSON.serialize()
.
nếu bạn đang sử dụng Jackson, sau đó bạn có thể deserialize chuỗi yêu cầu JSON bằng cách làm bất kỳ những:
1. Tạo một tùy chỉnh Jackson deserialize mô-đun
2. phân tích cú pháp JSON mình
public Child parseJackson(String jsonRequest) {
// what we need
ObjectMapper mapper;
JsonNode root, parentNode;
// your models
Child child;
Parent parent;
// assign
mapper = new ObjectMapper();
root = mapper.readTree(jsonRequest); // deserialize JSON as tree
parentNode = root.get("parent"); // get the "parent" branch
// assign (again)
child = mapper.readValue(root, Child.class);
parent = mapper.readValue(parentNode, Parent.class);
child.setParent(parent);
return child;
}
Mặt trái của phương pháp này là bạn phải phân tích cú pháp cho mọi JsonRequest đơn lẻ với các đối tượng lồng nhau và sẽ lộn xộn khi thứ Đây là một cấu trúc lồng nhau phức tạp. Nếu đây là một vấn đề, tôi đề nghị bạn làm như # 3
3. tạo ra một tùy chỉnh lớp Jackson ObjectMapper để tự động hóa quá trình này
Ý tưởng là để xây dựng quy trình chung cho # 2 để nó có thể xử lý bất kỳ yêu cầu lồng nhau nào.
public class CustomObjectMapper extends ObjectMapper {
// here's the method you need
@Override
public <T> T readValue(String src, Class<T> type)
throws IOException, JsonParseException, JsonMappingException {
JsonNode root = this.readTree(src);
try {
return readNestedValue(root, type);
} catch (InstantiationException | IllegalAccessException | IOException
| IllegalArgumentException | InvocationTargetException e) {
return super.readValue(src, type);
}
}
// if you're using Spring, I suggest you implement this method as well
// since Spring's MappingJacksonHttpMessageConverter class will call
// this method.
@Override
public <T> T readValue(InputStream src, JavaType type)
throws IOException, JsonParseException, JsonMappingException {
JsonNode root = this.readTree(src);
try {
return readNestedValue(root, (Class<T>) type.getRawClass());
} catch (InstantiationException | IllegalAccessException | IOException
| IllegalArgumentException | InvocationTargetException e) {
return super.readValue(src, type);
}
}
// we need this to recursively scan the tree node
protected <T> T readNestedValue(JsonNode root, Class<T> type)
throws InstantiationException, IllegalAccessException, IOException,
IllegalArgumentException, InvocationTargetException {
// initialize the object use ObjectMapper's readValue
T obj = super.readValue(root, type);
Iterator it = root.getFieldNames();
while (it.hasNext()) {
String name = (String) it.next();
String camelCaseName = name.substring(0, 1).toUpperCase() + name.substring(1);
JsonNode node = root.get(name);
Field f;
try {
f = type.getDeclaredField(name);
} catch (NoSuchFieldException e) {
f = findFieldInSuperClass(name, type.getSuperclass());
}
// if no field found then ignore
if (f == null) continue;
Method getter, setter;
try {
getter = type.getMethod("get" + camelCaseName);
} catch (NoSuchMethodException e) {
getter = findGetterInSuperClass("get" + camelCaseName, type.getSuperclass());
}
// if no getter found or it has been assigned then ignore
if (getter == null || getter.invoke(obj) != null) continue;
try {
setter = type.getMethod("set" + camelCaseName);
} catch (NoSuchMethodException ex) {
setter = findSetterInSuperClass("set" + camelCaseName, type.getSuperclass(), f.getType());
}
// if no setter found then ignore
if (setter == null) continue;
setter.invoke(obj, readNestedValue(node, f.getType()));
}
return obj;
}
// we need this to search for field in super class
// since type.getDeclaredField() will only return fields that in the class
// but not super class
protected Field findFieldInSuperClass(String name, Class sClass) {
if (sClass == null) return null;
try {
Field f = sClass.getDeclaredField(name);
return f;
} catch (NoSuchFieldException e) {
return findFieldInSuperClass(name, sClass.getSuperclass());
}
}
protected Method findGetterInSuperClass(String name, Class sClass) {
if (sClass == null) return null;
try {
Method m = sClass.getMethod(name);
return m;
} catch (NoSuchMethodException e) {
return findGetterInSuperClass(name, sClass.getSuperclass());
}
}
protected Method findSetterInSuperClass(String name, Class sClass, Class type) {
if (sClass == null) return null;
try {
Method m = sClass.getMethod(name, type);
return m;
} catch (NoSuchMethodException e) {
return findSetterInSuperClass(name, sClass.getSuperclass(), type);
}
}
}
Nếu bạn đang sử dụng Spring, thì bước cuối cùng sẽ đăng ký lớp này là Spring bean.
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="objectMapper">
<bean class="x.y.z.CustomObjectMapper"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
với những thiết lập bạn có thể dễ dàng sử dụng
@RequestMapping("/saveChild.json")
@ResponseBody
public Child saveChild(@RequestBody Child child) {
// do something with child
return child;
}
Hope this helps :)
Bạn có thể làm điều này bằng cách định nghĩa MessageBodyReader của riêng bạn, nhưng tôi phải tự hỏi tại sao ... ? – Perception
Vì tôi đang sử dụng ExtJS và nó đã gửi JSON với định dạng như trên. –
Chúng tôi có khách hàng Ext.js trong tất cả các giải pháp của chúng tôi. Nhận GUI của dev để sửa mô hình của họ. – Perception