私はJacksonを見てきましたが、マップをJSONに変換してから、結果のJSONをPOJOに変換する必要があるようです。
Map を直接 POJO に変換する方法はありますか?
私はJacksonを見てきましたが、マップをJSONに変換してから、結果のJSONをPOJOに変換する必要があるようです。
Map を直接 POJO に変換する方法はありますか?
まあ、ジャクソンでもそれを達成できます。(ジャクソンの使用を検討していたので、より快適なようです)。
ObjectMapper
のconvertValue
メソッドを使用します。
final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
final MyPojo pojo = mapper.convertValue(map, MyPojo.class);
JSON 文字列などに変換する必要はありません。直接変換ははるかに高速です。
Gsonを使用したソリューション:
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);
クラスにジェネリック型がある場合は、TypeReference
withを使用する必要がありますconvertValue()
。
final ObjectMapper mapper = new ObjectMapper();
final MyPojo<MyGenericType> pojo = mapper.convertValue(map, new TypeReference<MyPojo<MyGenericType>>() {});
また、それを使用して pojo を元にjava.util.Map
戻すこともできます。
final ObjectMapper mapper = new ObjectMapper();
final Map<String, Object> map = mapper.convertValue(pojo, new TypeReference<Map<String, Object>>() {});
はい、JSON への中間変換を回避することは間違いなく可能です。Dozerのようなディープ コピー ツールを使用すると、マップを直接 POJO に変換できます。簡単な例を次に示します。
POJO の例:
public class MyPojo implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String name;
private Integer age;
private Double savings;
public MyPojo() {
super();
}
// Getters/setters
@Override
public String toString() {
return String.format(
"MyPojo[id = %s, name = %s, age = %s, savings = %s]", getId(),
getName(), getAge(), getSavings());
}
}
サンプル変換コード:
public class CopyTest {
@Test
public void testCopyMapToPOJO() throws Exception {
final Map<String, String> map = new HashMap<String, String>(4);
map.put("id", "5");
map.put("name", "Bob");
map.put("age", "23");
map.put("savings", "2500.39");
map.put("extra", "foo");
final DozerBeanMapper mapper = new DozerBeanMapper();
final MyPojo pojo = mapper.map(map, MyPojo.class);
System.out.println(pojo);
}
}
出力:
MyPojo[id = 5、名前 = ボブ、年齢 = 23、貯蓄 = 2500.39]
注: ソース マップを に変更すると、Map<String, Object>
任意の深さでネストされたプロパティをコピーできます (Map<String, String>
取得できるレベルは 1 つだけです)。
Jackson と BeanUtils の両方をテストしたところ、BeanUtils の方がはるかに高速であることがわかりました。
私のマシン(Windows8.1、JDK1.7)では、この結果が得られました。
BeanUtils t2-t1 = 286
Jackson t2-t1 = 2203
public class MainMapToPOJO {
public static final int LOOP_MAX_COUNT = 1000;
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("success", true);
map.put("data", "testString");
runBeanUtilsPopulate(map);
runJacksonMapper(map);
}
private static void runBeanUtilsPopulate(Map<String, Object> map) {
long t1 = System.currentTimeMillis();
for (int i = 0; i < LOOP_MAX_COUNT; i++) {
try {
TestClass bean = new TestClass();
BeanUtils.populate(bean, map);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
long t2 = System.currentTimeMillis();
System.out.println("BeanUtils t2-t1 = " + String.valueOf(t2 - t1));
}
private static void runJacksonMapper(Map<String, Object> map) {
long t1 = System.currentTimeMillis();
for (int i = 0; i < LOOP_MAX_COUNT; i++) {
ObjectMapper mapper = new ObjectMapper();
TestClass testClass = mapper.convertValue(map, TestClass.class);
}
long t2 = System.currentTimeMillis();
System.out.println("Jackson t2-t1 = " + String.valueOf(t2 - t1));
}}