एक नक्शा <स्ट्रिंग, स्ट्रिंग> एक POJO में कनवर्ट करें


186

मैं जैक्सन को देख रहा हूं, लेकिन ऐसा लगता है कि मुझे मैप को JSON में बदलना होगा, और फिर परिणामस्वरूप JSON को POJO में बदलना होगा।

क्या मानचित्र को सीधे POJO में बदलने का कोई तरीका है?

जवाबों:


355

ठीक है, आप जैक्सन के साथ भी वह हासिल कर सकते हैं। (और यह अधिक आरामदायक प्रतीत होता है क्योंकि आप जैक्सन का उपयोग करने पर विचार कर रहे थे)।

उपयोग ObjectMapperकी convertValueविधि:

final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
final MyPojo pojo = mapper.convertValue(map, MyPojo.class);

JSON स्ट्रिंग या कुछ और में बदलने की कोई आवश्यकता नहीं है; प्रत्यक्ष रूपांतरण बहुत तेजी से करता है।


8
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.3'
ObjectMapper

5
ConvertValue का उपयोग करना सही उत्तर है, लेकिन हर बार एक ObjectMapper उदाहरण न बनाएं। यह महंगा और थ्रेड-सेफ है, इसलिए इसे बनाएं और इसे कहीं पर कैशे करें।
ग्लेड

1
क्या आप जानते हैं कि इसके विपरीत कैसे किया जाता है - या किसी वस्तु को मानचित्र <स्ट्रिंग, ऑब्जेक्ट> में कैसे परिवर्तित किया जाए?
anon58192932

2
@RaduSimionescu ने यह पता लगाया कि कैसे नेस्टेड मैप्स / सूचियों के साथ वस्तुओं को गहरी-रूपांतरित करने के लिए एक Map<String, Object>उदाहरण के लिए?
Anon58192932

यदि आप इस उत्तर का अनुसरण करते हैं तो @ anon58192932 यह काम करता है। मैं बस कुछ अजीब वस्तुओं के साथ काम कर रहा था, जो सूची के नक्शे के रूप में मॉडलिंग कर रहे थे और जब क्रमिक रूप से अप्रत्याशित परिणाम मिल रहे थे। लेकिन यह एक और मुद्दा था,
जैकसन के

60

Gson के साथ एक समाधान :

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

1
क्या होगा इसके विपरीत
Prbs


मैप को जसन में बदलने की आवश्यकता नहीं है। map.toString () पर्याप्त है। Gson gson = new Gson (); MyPojo पूजो = gson.fromJson (map.toString (), MyPojo.class);
एसाकियाप्पन ।E

1
@ Esakkiappan.E, आपको क्यों लगता है map.toString()कि सही स्ट्रिंग प्रदान करेगा? एक कार्यान्वयन toString()एक विशिष्ट प्रारूप की गारंटी नहीं देता है।
एलिकएल्ज़िन-किलाका

4

हां, इसका निश्चित रूप से JSON के मध्यवर्ती रूपांतरण से बचने के लिए संभव है। डोजर जैसे डीप-कॉपी टूल का उपयोग करके आप मैप को सीधे 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, name = Bob, उम्र = 23, बचत = 2500.39]

नोट: यदि आप अपने स्रोत के नक्शे को बदलते हैं Map<String, Object>तो आप मनमाने ढंग से गहरी नेस्टेड संपत्तियों की नकल कर सकते हैं ( Map<String, String>आप केवल एक स्तर प्राप्त करते हैं)।


1
आप मानचित्र से POJO तक "गहरी प्रतिलिपि" कैसे कर सकते हैं? उदाहरण के लिए कहें कि आपके पास एक User.class है जो एक Address.class को एनकैप्सुलेट करता है और मैप में "address.city", "address.zip" जैसी कुंजी है और इन्हें User.Address.City और User.Address.Zip को मैप करना होगा। ? यह ऑब्जेक्ट की ग्राफ़ के उप-स्तर के रूप में मैप कुंजी में डॉट को स्वचालित रूप से व्याख्या नहीं करता है।
21x पर szxnyc

4

अगर आप अपने वर्ग में सामान्य प्रकार है कि आप उपयोग करना चाहिए TypeReferenceसाथ convertValue()

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

इसके अलावा आप उपयोग कर सकते हैं कि एक पूजो को java.util.Mapवापस बदलने के लिए ।

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

2

मैंने जैक्सन और बीनटिल्स दोनों का परीक्षण किया है और पता चला है कि बीनटिल्स बहुत तेज है।
मेरी मशीन में (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));
}}

5
अंतर यह है: जैक्सन के पास एक पूरे प्रकार का रूपांतरण ढांचा है। जैसे कि Mapइसमें सम्‍मिलित है map.put("data","2016-06-26")और TestClassइसका एक क्षेत्र है private LocalDate data;, तो जैक्सन चीजों को प्राप्त करने में सक्षम होगा, जबकि बीन यूटिल्स विफल हो जाएगा।
बेंजामिन एम

6
मैंने सुना है कि ObjectMapperउदाहरण बनाना एक समय / संसाधन लेने वाली प्रक्रिया है, और इसे हर बार नए सिरे से बनाने के बजाय एक मैपर इंस्टेंस का उपयोग करने की सिफारिश की जाती है। मुझे लगता है कि टेस्ट लोप से इसे बाहर निकालना बेहतर होगा
मिक्साज़

3
एक निष्पक्ष परीक्षा नहीं, चूंकि बीन यूटिल्स पहले पुनरावृत्ति के बाद कैश करने में सक्षम है, जबकि ऑब्जेक्टमैपर को कभी मौका नहीं दिया जाता है।
लुकास रॉस

1

जैक्सन का उपयोग करते हुए अब तक प्रदान किए गए उत्तर बहुत अच्छे हैं, लेकिन फिर भी आपके पास विभिन्न प्रकारों को परिवर्तित करने में मदद करने के लिए एक उपयोग फ़ंक्शन हो सकता POJOहै:

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

0

मैप को POJO उदाहरण में परिवर्तित करें। मैप की कुंजी को रेखांकित करें और फ़ील्ड चर कूबड़ है।

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

App.class उदाहरण का परीक्षण करें

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)
 */

0

@Hamez यदि कई डेटा का उपयोग करते हैं, तो प्रकाश डेटा को बदलने के लिए जैक्सन का उपयोग करें, अपाचे का उपयोग करें ... 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; } }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.