Een kaart converteren<String, String> naar een POJO

Ik heb naar Jackson gekeken, maar het lijkt erop dat ik de kaart naar JSON zou moeten converteren en vervolgens de resulterende JSON naar de POJO.

Is er een manier om een ​​kaart rechtstreeks naar een POJO te converteren?


Antwoord 1, autoriteit 100%

Nou, dat kun je ook met Jackson bereiken. (en het lijkt comfortabeler te zijn sinds je overweegt Jackson te gebruiken).

Gebruik Gson:

Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);

Antwoord 3, autoriteit 2%

als je generieke typen in je klas hebt, moet je TypeReferencegebruiken met convertValue().

final ObjectMapper mapper = new ObjectMapper();
final MyPojo<MyGenericType> pojo = mapper.convertValue(map, new TypeReference<MyPojo<MyGenericType>>() {});

Je kunt dat ook gebruiken om een ​​pojo naar java.util.Mapterug te converteren.

final ObjectMapper mapper = new ObjectMapper();
final Map<String, Object> map = mapper.convertValue(pojo, new TypeReference<Map<String, Object>>() {});

Antwoord 4

Ja, het is zeker mogelijk om de tussentijdse conversie naar JSON te vermijden. Met behulp van een deep-copy tool zoals Dozerkun je de kaart direct converteren naar een POJO. Hier is een simplistisch voorbeeld:

Voorbeeld 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());
    }
}

Voorbeeld van conversiecode:

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);
    }
}

Uitvoer:

MyPojo[id = 5, naam = Bob, leeftijd = 23, spaargeld = 2500,39]

Opmerking: als u uw bronkaart wijzigt in een Map<String, Object>, kunt u willekeurig diep geneste eigenschappen kopiëren (met Map<String, String>je krijgt maar één niveau).


Antwoord 5

ObjectMapper objectMapper = new ObjectMapper();
 //if all properties are not in class use this
 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 final MyPojo pojo =     objectMapper.convertValue(map, MyPojo.class);

hetzelfde als het eerste antwoord, maar ik kreeg een foutmelding omdat ik niet wil dat alle eigenschappen van de kaart naar de calss worden geconverteerd. en ik vond objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);dit als de oplossing


Antwoord 6

Ik heb zowel Jackson als BeanUtils getest en ontdekte dat BeanUtils veel sneller is.
In mijn machine (Windows8.1 , JDK1.7) kreeg ik dit resultaat.

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));
}}

Antwoord 7

De antwoorden die tot nu toe zijn gegeven met Jackson zijn zo goed, maar toch zou je een util-functie kunnen hebben om je te helpen bij het converterenverschillende POJOs als volgt:

   public static <T> T convert(Map<String, Object> aMap, Class<T> t) {
        try {
            return objectMapper
                    .convertValue(aMap, objectMapper.getTypeFactory().constructType(t));
        } catch (Exception e) {
            log.error("converting failed! aMap: {}, class: {}", getJsonString(aMap), t.getClass().getSimpleName(), e);
        }
        return null;
    }

Antwoord 8

converteer kaart naar voorbeeld POJO. Merk op dat de kaartsleutel onderstreping bevat en veldvariabele is bult.

User.class POJO

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class User {
    @JsonProperty("user_name")
    private String userName;
    @JsonProperty("pass_word")
    private String passWord;
}

De App.class test het voorbeeld

import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
public class App {
    public static void main(String[] args) {
        Map<String, String> info = new HashMap<>();
        info.put("user_name", "Q10Viking");
        info.put("pass_word", "123456");
        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.convertValue(info, User.class);
        System.out.println("-------------------------------");
        System.out.println(user);
    }
}
/**output
-------------------------------
User(userName=Q10Viking, passWord=123456)
 */

Antwoord 9

@Hamedz
als je veel gegevens gebruikt, gebruik dan Jackson om te converteren
lichte gegevens, gebruik apache…
Testcase:


import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
public class TestPerf {
    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("number", 1000);
        map.put("longer", 1000L);
        map.put("doubler", 1000D);
        map.put("data1", "testString");
        map.put("data2", "testString");
        map.put("data3", "testString");
        map.put("data4", "testString");
        map.put("data5", "testString");
        map.put("data6", "testString");
        map.put("data7", "testString");
        map.put("data8", "testString");
        map.put("data9", "testString");
        map.put("data10", "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));
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class TestClass {
        private Boolean success;
        private Integer number;
        private Long longer;
        private Double doubler;
        private String data1;
        private String data2;
        private String data3;
        private String data4;
        private String data5;
        private String data6;
        private String data7;
        private String data8;
        private String data9;
        private String data10;
    }
}

Other episodes