source

Java 객체(빈)를 키와 값의 쌍으로 변환하는 방법(또는 그 반대)

goodcode 2022. 9. 4. 15:02
반응형

Java 객체(빈)를 키와 값의 쌍으로 변환하는 방법(또는 그 반대)

getXX 및 setXXX 속성만 있는 매우 단순한 Java 객체가 있다고 가정해 보겠습니다.이 오브젝트는 값(기본적으로 레코드 또는 타입 세이프(및 퍼포먼스) 맵) 처리에만 사용됩니다.종종 이 개체를 키 값 쌍(문자열 또는 유형 안전)으로 변환하거나 키 값 쌍에서 이 개체로 변환해야 합니다.

이 변환을 수행하기 위해 반사 또는 수동으로 코드를 작성하는 것 외에 이를 달성하는 가장 좋은 방법은 무엇입니까?

예를 들어 ObjectMessage 유형을 사용하지 않고 jms를 통해 이 개체를 전송하는 경우(또는 수신 메시지를 올바른 개체로 변환하는 경우)가 있습니다.

여러 가지 잠재적인 해결책이 있지만 하나만 더 추가해 봅시다.잭슨(JSON processing lib)을 사용하여 다음과 같이 "json-less" 변환을 수행합니다.

ObjectMapper m = new ObjectMapper();
Map<String,Object> props = m.convertValue(myBean, Map.class);
MyBean anotherBean = m.convertValue(props, MyBean.class);

(이 블로그 엔트리에는 몇 가지 예가 더 있습니다.)

기본적으로 호환되는 모든 유형을 변환할 수 있습니다.compatible은 유형에서 JSON으로 변환한 경우 해당 JSON에서 결과 유형으로 변환한 경우 엔트리가 일치함을 의미합니다(적절하게 설정되어 있는 경우 인식되지 않는 유형도 무시할 수 있습니다).

맵, 리스트, 어레이, 프리미티브, 콩과 같은 POJO 등 예상되는 케이스에 적합합니다.

아파치 공용 은 항상 있지만, 물론 후드 아래에 반사된 것을 사용합니다.

코드 생성만이 내가 생각할 수 있는 유일한 방법이야.개인적으로, 저는 일반적으로 재사용 가능한 반사 솔루션을 사용하였습니다(단, 코드의 해당 부분이 성능에 절대적으로 중요한 것은 제외).JMS를 사용하는 것은 과잉으로 들립니다(추가 의존관계, 그리고 그것은 의도된 바가 아닙니다).게다가, 아마 후드 밑에서도 반사를 이용하게 될 것입니다.

Java 객체를 Map으로 변환하는 방법입니다.

public static Map<String, Object> ConvertObjectToMap(Object obj) throws 
    IllegalAccessException, 
    IllegalArgumentException, 
    InvocationTargetException {
        Class<?> pomclass = obj.getClass();
        pomclass = obj.getClass();
        Method[] methods = obj.getClass().getMethods();


        Map<String, Object> map = new HashMap<String, Object>();
        for (Method m : methods) {
           if (m.getName().startsWith("get") && !m.getName().startsWith("getClass")) {
              Object value = (Object) m.invoke(obj);
              map.put(m.getName().substring(3), (Object) value);
           }
        }
    return map;
}

이렇게 부르면 되지

   Test test = new Test()
   Map<String, Object> map = ConvertObjectToMap(test);

아마 파티에 늦었을 거야.Jackson을 사용하여 속성 객체로 변환할 수 있습니다.이것은 Nested 클래스에 적합하며 a.b.c=value에 대한 키를 에 삽입할 경우 적합합니다.

JavaPropsMapper mapper = new JavaPropsMapper();
Properties properties = mapper.writeValueAsProperties(sct);
Map<Object, Object> map = properties;

접미사를 원하시면 그냥 하세요.

SerializationConfig config = mapper.getSerializationConfig()
                .withRootName("suffix");
mapper.setConfig(config);

이 종속성을 추가해야 합니다.

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-properties</artifactId>
</dependency>

Java 8 에서는, 다음과 같이 시험할 수 있습니다.

public Map<String, Object> toKeyValuePairs(Object instance) {
    return Arrays.stream(Bean.class.getDeclaredMethods())
            .collect(Collectors.toMap(
                    Method::getName,
                    m -> {
                        try {
                            Object result = m.invoke(instance);
                            return result != null ? result : "";
                        } catch (Exception e) {
                            return "";
                        }
                    }));
}

를 들어 XStream + Jettison을 사용하는 JSON은 키 값 쌍이 있는 단순한 텍스트 형식입니다.예를 들어 Apache ActiveMQ JMS 메시지브로커에 의해 다른 플랫폼/언어와의 Java 객체 교환이 지원됩니다.

반사 및 그루비를 사용하면 다음과 같습니다.

def Map toMap(object) {             
return object?.properties.findAll{ (it.key != 'class') }.collectEntries {
            it.value == null || it.value instanceof Serializable ? [it.key, it.value] : [it.key,   toMap(it.value)]
    }   
}

def toObject(map, obj) {        
    map.each {
        def field = obj.class.getDeclaredField(it.key)
        if (it.value != null) {
            if (field.getType().equals(it.value.class)){
                obj."$it.key" = it.value
            }else if (it.value instanceof Map){
                def objectFieldValue = obj."$it.key"
                def fieldValue = (objectFieldValue == null) ? field.getType().newInstance() : objectFieldValue
                obj."$it.key" = toObject(it.value,fieldValue) 
            }
        }
    }
    return obj;
}

juffrou-reflect의 BeanWrapper를 사용합니다.성능이 매우 뛰어납니다.

다음은 콩을 맵으로 변환하는 방법입니다.

public static Map<String, Object> getBeanMap(Object bean) {
    Map<String, Object> beanMap = new HashMap<String, Object>();
    BeanWrapper beanWrapper = new BeanWrapper(BeanWrapperContext.create(bean.getClass()));
    for(String propertyName : beanWrapper.getPropertyNames())
        beanMap.put(propertyName, beanWrapper.getValue(propertyName));
    return beanMap;
}

내가 직접 주프루를 개발했어오픈 소스이므로 자유롭게 사용 및 수정할 수 있습니다.그리고 그것에 관해 질문이 있으시면 기꺼이 답변해 드리겠습니다.

건배.

카를로스

스프링을 사용할 때는 스프링 적분 객체-to-map-to-transformer를 사용할 수도 있습니다.이것만을 위해 봄을 종속물로 추가할 필요는 없을 것이다.

매뉴얼에 대해서는 http://docs.spring.io/spring-integration/docs/4.0.4.RELEASE/reference/html/messaging-transformation-chapter.html에서 "Object-to-Map Transformer"를 검색하십시오.

기본적으로 입력으로 지정된 개체에서 도달 가능한 개체 그래프 전체를 통과하고 개체의 모든 원시 유형/문자열 필드에서 맵을 생성합니다.다음의 어느쪽인가를 출력하도록 설정할 수 있습니다.

  • 플랫 맵: {root Object}.someField=Response, rootObject.leafObject.someField=SomeField}, 또는
  • 구조화된 맵: {someField=Map, leafObject={someField=Map}}.

다음은 해당 페이지의 예입니다.

public class Parent{
    private Child child;
    private String name; 
    // setters and getters are omitted
}

public class Child{
   private String name; 
   private List<String> nickNames;
   // setters and getters are omitted
}

출력은 다음과 같습니다.

{person.name=George, person.child.name=Jenna, person.child.nick Names [0] = person.child.name=Jenna, person . child . etc }

역변압기도 사용할 수 있습니다.

Joda 프레임워크를 사용할 수 있습니다.

http://joda.sourceforge.net/

Joda Properties를 활용하십시오.다만, 특정의 방법으로 콩을 작성해, 특정의 인터페이스를 실장할 필요가 있습니다.단, 특정 클래스의 속성 맵을 반영하지 않고 반환할 수 있습니다.샘플 코드는 다음과 같습니다.

http://pbin.oogly.co.uk/listings/viewlistingdetail/0e78eb6c76d071b4e22bbcac748c57

콜을 각 getter 및 setter에 하드코드하지 않는 경우는 리플렉션만이 이러한 메서드를 호출하는 유일한 방법입니다(단, 어려운 것은 아닙니다).

Properties 객체를 사용하여 실제 데이터를 보관하고 각 getter와 setter를 호출하여 get/set하도록 문제의 클래스를 리팩터링할 수 있습니까?그러면 하고 싶은 일에 딱 맞는 구조를 갖게 되겠네요.키 값 형식으로 저장하고 로드하는 방법도 있습니다.

가장 좋은 해결책은 도저를 사용하는 것입니다.매퍼 파일에는 다음과 같은 것이 필요합니다.

<mapping map-id="myTestMapping">
  <class-a>org.dozer.vo.map.SomeComplexType</class-a>
  <class-b>java.util.Map</class-b>
</mapping> 

그게 다야, 나머지는 도저가 알아서 해!!!

도저 문서 URL

물론 가장 간단한 변환 방법이 있습니다. 변환은 전혀 없습니다!

클래스에서 정의된 개인 변수를 사용하는 대신 인스턴스에 대한 값을 저장하는 해시맵만 클래스에 포함시킵니다.

그런 다음 getters와 setters가 돌아와 해시맵에 대한 값을 설정하고 맵으로 변환할 때 voila! - 이미 맵입니다.

약간의 AOP 마법사를 사용하면 개별 getter 및 setter를 실제로 쓸 필요 없이 각 값 이름에 고유한 getter 및 setter를 계속 사용할 수 있으므로 콩 고유의 유연성이 유지됩니다.

Java 8 스트림필터 수집기 속성을 사용할 수 있습니다.

public Map<String, Object> objectToMap(Object obj) {
    return Arrays.stream(YourBean.class.getDeclaredMethods())
            .filter(p -> !p.getName().startsWith("set"))
            .filter(p -> !p.getName().startsWith("getClass"))
            .filter(p -> !p.getName().startsWith("setClass"))
            .collect(Collectors.toMap(
                    d -> d.getName().substring(3),
                    m -> {
                        try {
                            Object result = m.invoke(obj);
                            return result;
                        } catch (Exception e) {
                            return "";
                        }
                    }, (p1, p2) -> p1)
            );
}

JavaDude Bean Annotation Processor가 이를 위한 코드를 생성합니다.

http://javadude.googlecode.com

예를 들어 다음과 같습니다.

@Bean(
  createPropertyMap=true,
  properties={
    @Property(name="name"),
    @Property(name="phone", bound=true),
    @Property(name="friend", type=Person.class, kind=PropertyKind.LIST)
  }
)
public class Person extends PersonGen {}

위의 명령어는 @Bean을 사용하여 정의된 모든 속성의 맵을 생성하는 createPropertyMap() 메서드를 포함하는 슈퍼클래스 PersonGen을 생성합니다.

(다음 버전에서는 API를 약간 변경합니다.주석 속성은 defineCreatePropertyMap=true가 됩니다.)

범용 변환 서비스를 작성해야 합니다.generics를 사용하여 모든 개체를 key=> value 및 back으로 변환할 수 있습니다.

어떤 필드가 키여야 합니까?빈에서 이 필드를 가져와 값 맵에 다른 모든 과도하지 않은 값을 추가합니다.

돌아가는 길은 꽤 쉬워요.키(x)를 읽고 먼저 키를 쓴 다음 모든 목록 항목을 새 개체에 다시 씁니다.

아파치 커먼즈 을 사용하면 콩의 속성 이름을 얻을 수 있습니다!

정말로 퍼포먼스를 필요로 하는 경우는, 코드 생성 루트를 사용할 수 있습니다.

이것은, 자신의 성찰과 Aspect J ITD의 믹스인 구축에 의해서, 온으로 실시할 수 있습니다.

아니면 Spring Roo를 사용해서 Spring Roo Addon을 만들 수도 있어요.당신의 Roo Addon은 위와 유사한 작업을 수행하지만 Spring Roo를 사용하는 모든 사용자가 사용할 수 있으며 런타임 주석을 사용할 필요가 없습니다.

둘 다 해봤어요.사람들은 Spring Roo에 똥을 쌌지만 그것은 자바에 대한 가장 포괄적인 코드 생성이다.

한 가지 다른 방법이 있어요

BeanWrapper는 속성 값을 설정 및 가져오거나(개별 또는 대량), 속성 설명자를 가져오거나 속성을 쿼리하여 읽기 가능 또는 쓰기 가능 여부를 확인하는 기능을 제공합니다.

Company c = new Company();
 BeanWrapper bwComp = BeanWrapperImpl(c);
 bwComp.setPropertyValue("name", "your Company");

단순한 객체 트리에서 키 값 목록 매핑에 관해서는, 여기서 키는 객체의 루트 요소에서 검사 중인 리프까지의 도트 경로 설명일 수 있습니다.트리에서 키 값 목록으로의 변환은 객체에서 xml 매핑에 필적합니다.XML 문서 내의 각 요소는 정의된 위치를 가지며 경로로 변환할 수 있습니다.따라서 XStream을 기본적이고 안정적인 변환 도구로 채택하여 계층형 드라이버와 라이터 부분을 자체 구현으로 교체하였습니다.또한 XStream에는 기본 경로 추적 메커니즘이 포함되어 있으며, 이 메커니즘은 다른 두 가지 경로와 결합되어 작업에 적합한 솔루션으로 이어집니다.

Jackson 라이브러리의 도움으로 String/integer/double 유형의 모든 클래스 속성과 Map 클래스의 각 값을 찾을 수 있었습니다.(reflections api 사용 안 함!

TestClass testObject = new TestClass();
com.fasterxml.jackson.databind.ObjectMapper m = new com.fasterxml.jackson.databind.ObjectMapper();

Map<String,Object> props = m.convertValue(testObject, Map.class);

for(Map.Entry<String, Object> entry : props.entrySet()){
    if(entry.getValue() instanceof String || entry.getValue() instanceof Integer || entry.getValue() instanceof Double){
        System.out.println(entry.getKey() + "-->" + entry.getValue());
    }
}

Gson을 사용함으로써

  1. POJO 변환objectJson에게
  2. Json을 맵으로 변환

        retMap = new Gson().fromJson(new Gson().toJson(object), 
                new TypeToken<HashMap<String, Object>>() {}.getType()
        );
    

잭슨 라이브러리를 사용하여 Java 객체를 Map으로 쉽게 변환할 수 있습니다.

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.6.3</version>
</dependency>

Android 프로젝트에서 사용하는 경우 다음과 같이 앱의 build.gradle에 Jackson을 추가할 수 있습니다.

implementation 'com.fasterxml.jackson.core:jackson-core:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.9.8'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.8'

구현 예시

public class Employee {

    private String name;
    private int id;
    private List<String> skillSet;

    // getters setters
}

public class ObjectToMap {

 public static void main(String[] args) {

    ObjectMapper objectMapper = new ObjectMapper();

    Employee emp = new Employee();
    emp.setName("XYZ");
    emp.setId(1011);
    emp.setSkillSet(Arrays.asList("python","java"));

    // object -> Map
    Map<String, Object> map = objectMapper.convertValue(emp, 
    Map.class);
    System.out.println(map);

 }

}

출력:

{name=XYZ, id=1011, 스킬=[skills, java]}

언급URL : https://stackoverflow.com/questions/739689/how-to-convert-a-java-object-bean-to-key-value-pairs-and-vice-versa

반응형