Вопрос

Я пишу метод десериализатора, который выглядит так:

public <T> T deserialize(Object[] result, String[] fields, Class<T> type);

Таким образом, в основном мне будет передан массив результатов данных, который представляет собой все объекты, и тип класса T, который мне нужен для преобразования данных в массиве в типы данного класса, и создания нового класса типа T и возврата это.А String[] Поля — это имена полей, соответствующие данным в Object[] результат.Имена полей будут соответствовать классу T.

При кастинге необходимо будет использовать отражение данного класса, чтобы узнать тип каждого поля.

например.

result = ["Mike", "London", 28];
fields = ["name", "location", "age" ];

Класс Т =

public class GivenClass{

  private String name;
  private String location;
  private Integer age;

  public GivenClass(String name, String location, Integer age){
    this.name = name;
    this.location = location;
    this.age = age;
  }
}
Это было полезно?

Решение

Классовая реализация

static class GivenClass {

    private String name;
    private String location;
    private Integer age;

    public GivenClass(String name, String location, Integer age) {
        this.name = name;
        this.location = location;
        this.age = age;
    }

    public GivenClass(Map<String, Object> data) throws Exception {
        for (Field f : GivenClass.class.getDeclaredFields())
            f.set(this, data.get(f.getName()));
    }

    public Map<String, Object> serialize() throws Exception {
        Map<String, Object> fields = new HashMap<String, Object>();
        for (Field f : GivenClass.class.getDeclaredFields()) 
            fields.put(f.getName(), f.get(this));
        return fields;
    }

    @Override
    public String toString() {
        return "age=" + age + ", location=" + location + ", name=" + name;
    }
}

Пример:

public static void main(String[] args) throws Exception {

    GivenClass o1 = new GivenClass("Mike", "London", 28);

    Map<String, Object> serialized = o1.serialize();

    GivenClass o2 = new GivenClass(serialized);
    System.out.println(o2.toString());
}

Выход:

age=28, location=London, name=Mike

Другие советы

Вам нужно сделать обращение самостоятельно. Размышления не конвертируются (он будет только проверять тип объекта уже верен)

Размышления не дадут вам названия параметров метода/конструктора. (Вы можете получить их из байтового кода отладки, но это настоящая боль)

Подход, который я использую, заключается в том, чтобы использовать соглашение о том, что параметры конструктора находятся в том же порядке, что и поля. Вы также захотите предположить тип параметров конструктора и типы поля совпадают. ;)

Я также использовал бы примитивы вместо оберток, когда это возможно. Использовать int Если вы не хотите null быть действительным вариантом. Если это так, вы должны подумать о том, как вы хотите представить это. Для текста я обычно использую пустые строки или пустое поле для null или же NaN в зависимости от контекста.

Проблема в том, что в Java невозможно получить имена параметров конструктора.

Для этого конкретного примера вам понадобится конструктор по умолчанию, с помощью которого вы можете создать пустой объект.

public GivenClass() {
  super();
}

Затем вы можете использовать отражение, чтобы получить поля класса, а затем установить для них подходящее значение.

Но я думаю, что было бы гораздо проще аннотировать ваш конструктор, а затем получить информацию об аннотации в вашем deserialize метод.В этом случае вам не нужно будет получать поля и создавать пустой конструктор.

Пример:

Вам нужно создать такую ​​аннотацию:

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Property
{
    String value();
}

И затем вы можете использовать его в своем конструкторе следующим образом:

public GivenClass(@Property("name") String name, @Property("location") String location, @Property("age") Integer age) {
  // ...
}

Как говорит Питер Лоури, кастинг не преобразует строку в целое число.

Если ваш боб следует стандартным соглашениям о бобах (то есть у вас есть Getters & Setters), то вы можете использовать Beanuatils. Анкет Beanatils делает некоторые стандартные преобразования, и вы можете добавить больше, добавив Конвертор.

См. Следующий пример:

import org.apache.commons.beanutils.BeanUtils;

public class BeanUtilsTest {
    public static class Obj {
        private int number;
        private String string;

        public void setNumber(int number) {
            this.number = number;
        }
        public void setString(String string) {
            this.string = string;
        }

        public String toString() {
            return "number=" + number + " string=" + string;
        }
    }

    public static void main(String args[]) throws Exception {
        String[] values = new String[] { "1", "two" };
        String[] properties = new String[] { "number", "string" };

        Obj obj = new Obj();

        for (int i = 0; i < properties.length; i++) {
            BeanUtils.setProperty(obj, properties[i], values[i]);
        }

        System.out.println("obj=" + obj);
    }
}

Это производит как вывод:

obj=number=1 string=two

Обратите внимание, что приведенный выше пример имеет только сеттеры, но все еще работает.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top