简体   繁体   English

Java Reflection访问公共字段

[英]Java Reflection accessing public fields

I am writing a custom Serializer (Jackson JSON) for List class, this list could be inferred with different class types, so I'll need to grab object fields values using reflection. 我正在为List类编写一个自定义的Serializer(Jackson JSON),这个列表可以用不同的类类型推断,所以我需要使用反射来获取对象字段值。

Note, all this classes has public values (no setters and getters), so Invoking the getter will not be an option. 注意,所有这些类都有公共值(没有setter和getter),所以调用getter将不是一个选项。

This is what I get so far: 这是我到目前为止所得到的:

package com.xxx.commons.my.serializer;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.List;

public class ListSerializer extends StdSerializer<List> {

public ListSerializer() {
    super(List.class);
}

@Override
public void serialize(List aList, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

    if (aList != null) {

        jsonGenerator.writeStartObject();

        for (int index = 0 ; index < aList.size(); index++) {

            try {

                Object next = aList.get(index);

                List<Field> fields = FieldUtils.getAllFieldsList(next.getClass());

                Object object = next.getClass().newInstance();

                for (int j = 0 ; j < fields.size(); j ++ ) {

                    jsonGenerator.writeObjectField(String.format("%s[%s]",fields.get(j).getName(),index) , object);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        jsonGenerator.writeEndObject();
    }
}
}

MyTest MyTest的

package com.xxx.commons.my.serializer;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.Test;

public class ListSerializerTest {

    private ObjectMapper mapper = new ObjectMapper();

    @Test
    public void test() throws Exception {

        SimpleModule module = new SimpleModule();

        module.addSerializer(new ListSerializer());

        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        mapper.registerModule(module);

        MyTempClassParent parent = new MyTempClassParent();
        parent.mylist.add(new MyTempClass("1","2","3"));

        String json = mapper.writeValueAsString(parent);

        System.out.println(json);
    }   

}

Example classes: 示例类:

public class MyTempClass {

    public MyTempClass() {
    }

    public MyTempClass(String value1, String value2, String value3) {
        this.valueA = value1;
        this.valueB = value2;
        this.valueC = value3;
    }

    public String valueA;
    public String valueB;
    public String valueC;
}

public class MyTempClassParent {

   public List<MyTempClass> mylist = new LinkedList<>();
}

Any ideas or alternatives for writing this ? 写这个的任何想法或替代方案?

Maybe you should just use ObjectMapper with setting property accessor to get access to every field: 也许你应该只使用ObjectMapper设置属性访问器来访问每个字段:

ObjectMapper mapper = new ObjectMapper();
    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

    MyDtoAccessLevel dtoObject = new MyDtoAccessLevel();

    String dtoAsString = mapper.writeValueAsString(Arrays.asList(dtoObject));
    System.out.println(dtoAsString);

result: [{"stringValue":null,"intValue":0,"floatValue":0.0,"booleanValue":false}] dto: 结果:[{“stringValue”:null,“intValue”:0,“floatValue”:0.0,“booleanValue”:false}] dto:

class MyDtoAccessLevel {
    private String stringValue;
    int intValue;
    protected float floatValue;
    public boolean booleanValue;
    // NO setters or getters

--edit For getting values from objects by reflection: --edit用于通过反射从对象获取值:

    @Override
public void serialize(List aList, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {

    if (aList != null) {

        jsonGenerator.writeStartObject();

        for (int index = 0 ; index < aList.size(); index++) {

            try {

                Object next = aList.get(index);

                List<Field> fields = FieldUtils.getAllFieldsList(next.getClass());

                for (int j = 0 ; j < fields.size(); j ++ ) {

                    jsonGenerator.writeObjectField(String.format("%s[%s]",fields.get(j).getName(),index) , fields.get(j).get(next));
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        jsonGenerator.writeEndObject();
    }
}

Please write in question, what do you want to have in output. 请写下问题,你想在输出中有什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM