Получать и интерпретировать различные типы объектов JSON из одного сервлета

#java #json

#ява #json #java

Вопрос:

У меня есть несколько типов значений JSON, которые я хочу извлечь из одного сервлета URL. Например, ReadingType1, ReadingType2, ReadingType3 … каждый из них имеет свою собственную структуру.

Однако, согласно моему коду, когда я анализирую строку JSON и преобразую ее в объект Java, я должен указать тип объекта, к которому она будет приведена. Не существует механизма для проверки структуры JSON, чтобы определить, к какому типу объекта следует применить его в первую очередь.

 protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    StringBuffer sb = new StringBuffer();
    String line = null;
    try {
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
    } catch (Exception e) {
    }

    Gson gson = new Gson();
    Reading reading = gson.fromJson(sb.toString(), Reading.class);
}
  

Обратите внимание, что последняя строка указывает, что тип считывается при преобразовании его в объект.

Как вы проверяете структуру входных данных JSON, прежде чем определять, что это за объект?

Например.

 if (JSON has structure1) { reading = gson.fromJson(sb.toString(), ReadingType1.class); }

else if (JSON has structure2) { reading = gson.fromJson(sb.toString(), ReadingType2.class); }

else if (JSON has structure3) { reading = gson.fromJson(sb.toString(), ReadingType3.class); }
  

Комментарии:

1. Почему бы вам просто не использовать анализатор JSON для чтения типа класса из JSON? Конечно, сначала вам нужно будет включить тип класса в JSON, введите: 1

2. Предпочтительно, чтобы у вас были разные URL-адреса для разных объектов. (Правильное использование Rest). Если нет, то вы могли бы либо внедрить тип класса и протестировать String.contains ("classtype="ReadingType1""); , либо использовать блоки try catch

Ответ №1:

Я добавил в свой JSON строковый параметр, в котором указано имя класса.

 // sample JSON
{
    "factType":"SomeFact",
    "someParam":"value"
}

package com.acme.services;

import java.io.IOException;

import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;

/**
 * service that maps JSON to class
 * 
 * @author gal.nitzan.1
 *
 */

@Service
public class MapperService {
    private ObjectMapper mapper = new ObjectMapper();

    public MapperService() {
    }

    @SuppressWarnings("rawtypes")
    public Class mapToClass(String jsonString) throws IllegalFactPayloadException {
        if (jsonString == null || jsonString.length() == 0) {
            throw new IllegalFactPayloadException("jsonString can not be null or empty.");
        }

        Class clazz = null;
        ObjectNode node = null;

        try {
            node = mapper.readValue(jsonString, ObjectNode.class);
        }
        catch (JsonParseException e) {
            throw new IllegalFactPayloadException(e);
        }
        catch (JsonMappingException e) {
            throw new IllegalFactPayloadException(e);
        }
        catch (IOException e) {
            throw new IllegalFactPayloadException(e);
        }

        if (node.has("factType")) {
            try {
                clazz = Class.forName("com.acme.entities."   node.get("factType").asText());
            }
            catch (ClassNotFoundException e) {
                throw new IllegalFactPayloadException(e);
            }
        }
        else {
            throw new IllegalFactPayloadException("jsonString is missing factType attribute.");
        }

        return clazz;
    }
}
  

HTH,
Gal