Парсинг JSON-файл, загрузить


Я пытаюсь разобрать JSON и загружать файл. Я знаю, что формат JSON будет поступать как этот:

{
"list": [{
    "atttibute1": "value1",
    "atttibute2": "valu2",
    "atttibute3": "valu3",

},
{
    "atttibute1": "value4",
    "atttibute2": "value5",
    "atttibute3": "value6",

},
{
    "atttibute1": "value7",
    "atttibute2": "value8",
    "atttibute3": "value9",

}]
}

Я разработал код, чтобы создать таблицу для этого файла JSON при передаче на основе этого формата. Когда пользователь отправляет запрос остальное будет загрузить файл и затем вызвать этот парсер.

Есть ли способы улучшить код или сделать его более читабельным?

public class JSONParserFile {

    /**
     * save JSON file in database
     * @param file
     * @param tableName
     * @throws Exception
     */
    public void saveFile(MultipartFile file,String tableName) throws Exception {


        // get connection 
        Connection dbConnection = DB_Connection.getConnection();

        StringBuilder sbCreateTable = new StringBuilder( 1024 );

        JSONParserFile jsonParser=new JSONParserFile();


        List<String> listColumns=jsonParser.getTableColumns(file);

        //get size columns  
        int sizeColumns=listColumns.size();

        // check if colunms not emptm then append statement 
        if (!listColumns.isEmpty() ) { 
            sbCreateTable.append( "Create table " ).append( tableName.replaceAll(" ", "_").replaceAll("\'", "") ).append( " ( " );
        }

        //for loop colunms 
        for ( int i = 0; i < listColumns.size(); i ++ ) {

            sbCreateTable.append(listColumns.get(i).replaceAll(" ", "_"));
            sbCreateTable.append(" VARCHAR(255)");

            if(listColumns.size()-1!=i) {
                sbCreateTable.append(",");
            }

        }

        if ( listColumns.size() > 0 ) { 
            sbCreateTable.append(" )");
        }

        //create table 
        jsonParser.createTable(sbCreateTable,dbConnection);


        //insert records in table 
        jsonParser.getRecordsInsert(dbConnection,file,sizeColumns,tableName);


    }


    /**
     * get table columns from json Object 
     * @param file
     * @return
     */
    List<String> getTableColumns(MultipartFile file){
        List<String> columns=new ArrayList<String>();

        JSONParser parser = new JSONParser();

        //parse json objet file
        JSONObject obj;
        try {

            //parse JSON object 
            obj = (JSONObject )parser.parse(new InputStreamReader(file.getInputStream(), "UTF-8"));


            //get keys object
            Set<String> keys = obj.keySet();

            //get first keys 
            String keytList =keys.iterator().next().toString();

            //return list of objects 
            JSONArray array=(JSONArray)obj.get(keytList);

            //first object 
            JSONObject tempObject =(JSONObject)array.get(0);

            //GET ATTRIBUTES 
            Set<String> coulmns = tempObject.keySet();
            for (String attribute : coulmns) {

                columns.add(attribute);
            }
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return columns;
    }

    /**
     * 
     * create table based file 
     * @param sb
     * @param dbConnection
     */
    public void createTable(StringBuilder sb,Connection dbConnection){
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = dbConnection.prepareStatement(sb.toString());


            preparedStatement.execute();

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }



    /**
     * insert records excel sheeet in tables 
     * @param dbConnection
     * @throws Exception
     */
    void getRecordsInsert(Connection dbConnection,MultipartFile file,int sizeColumns ,String tableName) throws Exception{
        JSONParser parser = new JSONParser();

        StringBuilder sbInsert = new StringBuilder( 1024 );
        PreparedStatement preparedStatement = null;

        //parse json objet file
        JSONObject obj;
        try {

            obj = (JSONObject )parser.parse(new InputStreamReader(file.getInputStream(), "UTF-8"));

            //get keys object
            Set<String> keys = obj.keySet();

            //get first keys 
            String keytList =keys.iterator().next().toString();

            //return list of objects 
            JSONArray array=(JSONArray)obj.get(keytList);


            for (Object object : array) {
                //first object 
                JSONObject tempObject =(JSONObject)object;
                //rest 
                sbInsert.setLength(0);

                sbInsert.append("insert into "+tableName.trim().replaceAll(" ", "_")+" values(");
                int currentCellLenght=0;

                //GET ATTRIBUTES 
                Set<String> coulmns = tempObject.keySet();
                for (String attribute : coulmns) {

                     sbInsert.append("'"+tempObject.get(attribute).toString().replaceAll("\'", "")+"'");
                       currentCellLenght++;


                    //exit when reach last coulumns
                    if(currentCellLenght==sizeColumns) {
                        break;
                    }

                    //add insert rows 
                    if(currentCellLenght!=sizeColumns) {
                        sbInsert.append(",");
                    }
                }
                sbInsert.append(")");

                preparedStatement = dbConnection.prepareStatement(sbInsert.toString());

                preparedStatement.execute();


            }


        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

}


1397
3
задан 19 февраля 2018 в 07:02 Источник Поделиться
Комментарии
1 ответ

Вот мои замечания, в порядке тяжести:

Ошибки

(или ошибка-поведение)

1) утечки ресурсов:
Вы не закрывайте ИО ресурсы, которые вы используете (соединение с БД, и различные InputStreamс открытия входного файла). незакрытые ресурсы (утечки ака) оставить встраиваемыми или ОС - обработчики уровня открытия позади. даже если вы используете БД пул подключений (я надеюсь, что вы сделали, вы?), вы должны закрыть соединение, чтобы вернуть его к бассейну. Использовать Java для 7 попытки с ресурсами функцию, чтобы оптимально обрабатывать жизненный цикл ИО ресурсов

Примечание: PreparedStatement также выдвижным ресурса.

2) уязвимость SQL-инъекции:
при вставке данных с помощью SQL-оператора Insert не вставлять значения в отчете. Использование переменных связывания.

3) избыточные создания экземпляра:
третье заявление в saveFile() создает экземпляр JSONParserFile. поскольку метод не статический, у вас уже есть экземпляр JSONParserFile: this. использовать его.

Производительности

1) Анализ входного файла:
Вы распарсить входной файл дважды (и создать два незамкнутых InputStreamС). этим все сказано.

2) избыточные расчет размер:
если вы уже не поленились подсчитать listColumns.size() и положить его в int переменную sizeColumnsпочему ты продолжаешь называть size() метод дальнейшей обработки?

Дизайн

1) расширяемость:
Когда вы решите, что saveFile() принимает MultipartFile аргумент ограничивает полезность метода очень конкретный тип входного сигнала. Тем не менее, переработка saveFile() не полагаться на какую-либо особенность MultipartFile и может работать на любом InputStream. InputStream более общего назначения, чем MultipartFile так что вы сможете использовать тот же saveFile() для других сценариев.

если вы хотите сохранить клиент проблемы преобразования MultipartFile для InputStream вы можете предложить перегруженный вариант метода

  public void saveFile(MultipartFile file,String tableName) throws Exception {
// here we are responsible for the life-cycle of the input stream
try (InputStream is = file.getInputStream()) {
saveFile(is, tableName);
}
}

public void saveFile(InputStream file, String tableName) throws Exception {
// do work
}

2) модульность:
в JSONParserFile делает всю работу: НЛ операции чтения входного файла, парсинг JSON-файл, содержание, и все SQL для обработки. Это означает, что любые изменения на входе или выходе приведет к изменению этого класса монолит. это создает потенциальные проблемы побочных эффектов: когда вы замените JSON с XML, вы можете ввести ошибки в обработке SQL. Ради модульности (а также ясность) вы лучше сломать класса монолит на меньшие классы, которые заботятся об одном аспекте проблемы.

Читабельность

1) StringBuilderиспользование этого класса (май) есть прирост производительности, но вы платите за то, что в читабельности. большое время (ИМО). Вы также должны знать, что Java-компилятор заменяет знак плюс конкатенации строк с StringBuilder.append() в байткод. Только в очень конкретных ситуациях (частые циклы и такие) он на самом деле делает другое, чтобы явно использовать StringBuilder. Я бы сказал, что, как правило, конкатенация строк должно быть сделано со знаком плюс, если вы не знаете, у вас есть цикл, который перебирает тысячи единиц или сотен раз.

2) но этого не достаточно. даже если мы заменим StringBuilder С плюс знак конкатенации строк, это утверждение

"Create table " + tableName.replaceAll(" ", "_").replaceAll("\'", "") + " ( "; 

остается неясным, потому что трудно увидеть, где знак плюс среди всех остальных символов препинания. один способ решить эту проблему, нарушая в соответствии со знаком "плюс". Однако, если мы посмотрим на "картину", что у вас тут шаблон SQL-оператора, где вы хотите вставить таблицы и имена столбцов. вложение ценностей в строке опыта printf стиль форматирования:

String.format("Create table %s ( ", tableName.replaceAll(" ", "_").replaceAll("\'", "")); 

это гораздо лучше. вы могли бы рассмотреть нарушая вышеуказанное заявление к двум линиям для большей ясности.

3) вступление в строку:
В Java 8 поток API может (и должен) быть использован практически во всех местах, где for петли раньше. Это особенно верно в строке-соединения петель. Например, весь цикл, который используется в строительстве CREATE SQL-оператор можно заменить на одну строку:

listColumns.stream().collect(Collectors.joining(" VARCHAR(255),", "", " VARCHAR(255))"))

Можно спорить о увеличение читабельности. кто-то, кто знаком с Java 8 API и трансляция будет знать об этом сразу.

Соглашение Об Именовании

1) void getRecordsInsert()
геттер возвращения void?

5
ответ дан 20 февраля 2018 в 10:02 Источник Поделиться