使用javax.json从JSON String到Java Object [英] From JSON String to Java Object using javax.json
问题描述
我正在使用 com.google.gson.Gson
API将JSON字符串转换为Java对象:
I'm using the com.google.gson.Gson
API to convert a JSON string to a Java object:
Gson gson = new Gson();
User u = gson.fromJson(jsonString, User.class);
我想知道 javax.json中是否存在等效的API api做同等的事情。
谢谢!
I'd like to know if there's an equivalent API in javax.json api to do the equivalent. Thanks!
推荐答案
对于像Gson一样的oneliner,这绝对是不可能的。 javax.json
API的级别非常低。它只返回一个JSON对象结构,你需要将其细分并进一步映射到javabean。
This is definitely not possible with an oneliner like as with Gson. The javax.json
API is very low level. It only returns you a JSON object structure which you've to breakdown and map to a javabean further all by yourself.
为了达到(几乎)相同的效果 Gson#fromJson()
,这是样板代码的启动示例。在某种程度上支持参数化类型和javabeans。它是所有标准的Java SE API,javabeans在 java.beans
API的帮助下进行了内省。
In order to achieve (nearly) the same effect as Gson#fromJson()
, here's a kickoff example of the boilerplate code. Parameterized types and javabeans are supported to certain extent. It's all standard Java SE API, the javabeans are introspected with little help of java.beans
API.
@SuppressWarnings("unchecked")
public static <T> T fromJson(String json, Class<T> beanClass) {
JsonValue value = Json.createReader(new StringReader(json)).read();
return (T) decode(value, beanClass);
}
private static Object decode(JsonValue jsonValue, Type targetType) {
if (jsonValue.getValueType() == ValueType.NULL) {
return null;
}
else if (jsonValue.getValueType() == ValueType.TRUE || jsonValue.getValueType() == ValueType.FALSE) {
return decodeBoolean(jsonValue, targetType);
}
else if (jsonValue instanceof JsonNumber) {
return decodeNumber((JsonNumber) jsonValue, targetType);
}
else if (jsonValue instanceof JsonString) {
return decodeString((JsonString) jsonValue, targetType);
}
else if (jsonValue instanceof JsonArray) {
return decodeArray((JsonArray) jsonValue, targetType);
}
else if (jsonValue instanceof JsonObject) {
return decodeObject((JsonObject) jsonValue, targetType);
}
else {
throw new UnsupportedOperationException("Unsupported json value: " + jsonValue);
}
}
private static Object decodeBoolean(JsonValue jsonValue, Type targetType) {
if (targetType == boolean.class || targetType == Boolean.class) {
return Boolean.valueOf(jsonValue.toString());
}
else {
throw new UnsupportedOperationException("Unsupported boolean type: " + targetType);
}
}
private static Object decodeNumber(JsonNumber jsonNumber, Type targetType) {
if (targetType == int.class || targetType == Integer.class) {
return jsonNumber.intValue();
}
else if (targetType == long.class || targetType == Long.class) {
return jsonNumber.longValue();
}
else {
throw new UnsupportedOperationException("Unsupported number type: " + targetType);
}
}
private static Object decodeString(JsonString jsonString, Type targetType) {
if (targetType == String.class) {
return jsonString.getString();
}
else if (targetType == Date.class) {
try {
return new SimpleDateFormat("MMM dd, yyyy H:mm:ss a", Locale.ENGLISH).parse(jsonString.getString()); // This is default Gson format. Alter if necessary.
}
catch (ParseException e) {
throw new UnsupportedOperationException("Unsupported date format: " + jsonString.getString());
}
}
else {
throw new UnsupportedOperationException("Unsupported string type: " + targetType);
}
}
private static Object decodeArray(JsonArray jsonArray, Type targetType) {
Class<?> targetClass = (Class<?>) ((targetType instanceof ParameterizedType) ? ((ParameterizedType) targetType).getRawType() : targetType);
if (List.class.isAssignableFrom(targetClass)) {
Class<?> elementClass = (Class<?>) ((ParameterizedType) targetType).getActualTypeArguments()[0];
List<Object> list = new ArrayList<>();
for (JsonValue item : jsonArray) {
list.add(decode(item, elementClass));
}
return list;
}
else if (targetClass.isArray()) {
Class<?> elementClass = targetClass.getComponentType();
Object array = Array.newInstance(elementClass, jsonArray.size());
for (int i = 0; i < jsonArray.size(); i++) {
Array.set(array, i, decode(jsonArray.get(i), elementClass));
}
return array;
}
else {
throw new UnsupportedOperationException("Unsupported array type: " + targetClass);
}
}
private static Object decodeObject(JsonObject object, Type targetType) {
Class<?> targetClass = (Class<?>) ((targetType instanceof ParameterizedType) ? ((ParameterizedType) targetType).getRawType() : targetType);
if (Map.class.isAssignableFrom(targetClass)) {
Class<?> valueClass = (Class<?>) ((ParameterizedType) targetType).getActualTypeArguments()[1];
Map<String, Object> map = new LinkedHashMap<>();
for (Entry<String, JsonValue> entry : object.entrySet()) {
map.put(entry.getKey(), decode(entry.getValue(), valueClass));
}
return map;
}
else try {
Object bean = targetClass.newInstance();
for (PropertyDescriptor property : Introspector.getBeanInfo(targetClass).getPropertyDescriptors()) {
if (property.getWriteMethod() != null && object.containsKey(property.getName())) {
property.getWriteMethod().invoke(bean, decode(object.get(property.getName()), property.getWriteMethod().getGenericParameterTypes()[0]));
}
}
return bean;
}
catch (Exception e) {
throw new UnsupportedOperationException("Unsupported object type: " + targetClass, e);
}
}
用法:
User u = YourJsonUtil.fromJson(jsonString, User.class);
如果您看到 UnsupportedOperationException
来自 decodeXxx()
方法之一,只需将所需的转换逻辑添加到相关方法中。当然,这可以进一步重构以应用策略模式,以便它具有灵活性和可扩展性,但是我们基本上重新发明了Gson。
In case you're seeing an UnsupportedOperationException
coming from one of decodeXxx()
methods, just add the desired conversion logic to the method in question. Of course this could be refactored further to apply the strategy pattern and such so that it's flexible and extensible, but then we're basically reinventing Gson.
这篇关于使用javax.json从JSON String到Java Object的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!