Как преобразовать имя поля JSON в свойство класса Java bean с помощью Jackson - PullRequest
1 голос
/ 25 сентября 2019

У меня есть доступ к RESTful API, который возвращает строки JSON, например:

{
    "Container1": {
        "active": true
    },
    "Container2": {
        "active": false
    },
}

Проблема заключается в том, что RESTful API немного неправильно разработан.Имя поля уже содержит данные.С библиотекой Джексона невозможно десериализовать имя поля в имя свойства соответствующего класса Java-бина.Я предполагаю, что это не предназначено ни спецификацией JSON.Приведенную выше строку JSON необходимо десериализовать в экземпляр следующего класса:

public class Container {
    private Boolean active;
    private String name;
}

Я получаю UnrecognizedPropertyException для поля Container1.

Я подумал настроить, чтобы игнорировать неизвестные свойства и предоставить JsonDeserializer для этого свойства, например:

@JsonIgnoreProperties(ignoreUnknown = true)
public class Container {
    private Boolean active;
    private String name;

    @JsonDeserialize(using = FieldNameToPropertyDeserializer.class)
    public void setName(String name) {
        this.name = name;
    }
}

и FieldNameToPropertyDeserializer:

public class FieldNameToPropertyDeserializer extends StdDeserializer<String> {
    public FieldNameToPropertyDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
        return parser.getCurrentName();
    }
}

Вызов десериализации достигается следующим образом:

String jsonString = response.readEntity(String.class);
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader readerFor = objectMapper.readerFor(Container.class);
MappingIterator<Container> mappingIterator = readerFor.readValues(jsonString);
while (mappingIterator.hasNext()) {
    Container container = (Container) mappingIterator.next();
    containers.add(container);
}

Но я получаю только пустые объекты (свойства установлены на null), потому что синтаксический анализ свойств пропускается, так как я установил @JsonIgnoreProperties(ignoreUnknown = true).

Возможно ли это вообще?Или я должен потом реализовать что-то вроде постобработки?

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

Как насчет этого.Создайте класс ContainerActive, подобный этому

public class ContainerActive {
    private  boolean active;
    // constructors, setters, getters
}

И вы можете просто сделать

  Map<String, ContainerActive> map = mapper.readValue(jsonString, new TypeReference<Map<String, ContainerActive>>() {});

С этим вы будете иметь «Container1», «Container2» в качестве ключей и ContainerActive Object в качестве значений, которыеимеет активное поле.

1 голос
/ 25 сентября 2019

Просто быстрое решение, если объект таков, что весь его объект является контейнерным объектом, вы можете получить JSON внутри и JSONObject, который вы можете использовать ниже кода

import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class TestSO {

    public static void main(String[] args) throws JsonParseException, JsonMappingException, JSONException, IOException {
        String jsonString = "{\r\n" + 
                "    \"Container1\": {\r\n" + 
                "        \"active\": true\r\n" + 
                "    },\r\n" + 
                "    \"Container2\": {\r\n" + 
                "        \"active\": false\r\n" + 
                "    },\r\n" + 
                "}";

        JSONObject jsonObject = new JSONObject(jsonString);

        ObjectMapper mapper = new ObjectMapper();
        for (String key : jsonObject.keySet()) {
            Container container = mapper.readValue(jsonObject.get(key).toString(), Container.class);
            System.out.println(container);
        }   
    }

    static class Container{
        private String name;
        private Boolean active;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Boolean getActive() {
            return active;
        }
        public void setActive(Boolean active) {
            this.active = active;
        }
        @Override
        public String toString() {
            return "Container [name=" + name + ", active=" + active + "]";
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...