Pergunta

I have to parse data from JSON files and insert data into my database. There are three files:

  • countries

    [ { "id": 1, "name": "United States", "org_ids": [ 1, 2, 3 ] }, { "id": 2, "name": "China", "org_ids": [ 1, 3, 4 ] }, { "id": 3, "name": "Hong Kong", "org_ids": [ 1, 2 ] } ]

  • international organizations

    [ { "id": 1, "name": "UNO" }, { "id": 2, "name": "Organization of American States" }, { "id": 3, "name": "INTERPOL" }, { "id": 4, "name": "European Union" }, { "id": 5, "name": "The Commonwealth of Nations" } ]

  • continents

    [ { "id": 1, "name": "Africa" }, { "id": 2, "name": "North America" }, { "id": 3, "name": "South America" }, { "id": 4, "name": "Asia" }, { "id": 5, "name": "Europe" }, { "id": 6, "name": "Australia" } ]

Please don't pay attention to the contents of my JSONs, they don't contain real members of the listed international organizations. It's just an example.

Here I was advised to use the visitor design pattern. I fully agree to use it so as not to mix JSON reading logic with database logic.

My JSON parser class is below.

class JsonParser {

    private List<Country> mCountries;

    private abstract class BaseEntity {

        private String name;
        private long id;

        private BaseEntity(long id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public String toString() {
            return ID + COLON + SPACE + id + COMMA + SPACE + NAME + COLON + SPACE + name;
        }
    }

    class Country extends BaseEntity {

        private List<Long> orgsIds;

        public Country(long id, String name, List<Long> orgsIds) {
            super(id, name);
            this.orgsIds = new ArrayList<Long>();
            this.orgsIds.addAll(orgsIds);
        }

        public List<Long> getOrgsIds() {
            return orgsIds;
        }

        @Override
        public String toString() {
            return super.toString() + COMMA + SPACE + ORG_IDS + SPACE + orgsIds;
        }

    }
}

Now I can't understand how to apply the visitor pattern to the collection mCountries. I am planning to insert the whole list with bulkInsert method of ContentProvider class because it works a lot more quicker than insert.

I need an elegant solution.

Foi útil?

Solução

The solution.

I found the solution by myself. I didn't need the visitor pattern. I just implemented the following logic.

JsonPasrer.

This class only reads data from JSON files.

public class JsoinParser {

    /**
     * Reads a JSON file to a string
     * 
     * @param fileName JSON file name
     * @return null if reading failed
     */
    private String readToString(String fileName) throws IOException {
        StringBuilder resultBuilder = new StringBuilder();
        String filePath = mContext.getExternalFilesDir(null).getAbsolutePath() + File.separatorChar + fileName;
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(filePath));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                resultBuilder.append(line);
            }
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    Log.e("%s", "Failed to close the BufferedReader instance");
                }
            }
        }
        return resultBuilder.toString();

    }

    public List<Organization> readOrgs() throws JSONException, IOException {
        JSONArray array = new JSONArray(readToString(FilesNames.ORGS));
        List<Organization> list = new ArrayList<JsonParser.Organization>();
        // TODO: read here and fill
        return list;
    }

    public List<Continent> readContinents() throws JSONException, IOException {
        JSONArray array = new JSONArray(readToString(FilesNames.CONTINENTS));
        List<Continent> list = new ArrayList<JsonParser.Continent>();
        for (int i = 0; i < array.length(); i++) {
            JSONObject object = array.getJSONObject(i);
            list.add(new Continent(object.getLong(ID), object.getString(NAME)));
        }
        return list;
    }

    public List<Country> readCountries() throws JSONException, IOException {
        JSONArray array = new JSONArray(readToString(FilesNames.COUNTRIES));
        List<Country> list = new ArrayList<JsonParser.Country>();
        for (int i = 0; i < array.length(); i++) {
            JSONObject object = array.getJSONObject(i);
            long id = object.getLong(ID);
            String name = object.getString(NAME);
            List<Long> orgsIds = new ArrayList<Long>();
            try {
                JSONArray orgs = object.getJSONArray(ORGS_IDS);
                orgsIds = new ArrayList<Long>();
                for (int j = 0; j < orgs.length(); j++) {
                    orgsIds.add(orgs.getLong(j));
                }
            } catch (JSONException e) {
                Log.v("%s", name + " is not a member of any international organizations");
            }

            long continentId = object.getLong(CONTINENT_ID);
            list.add(new Country(id, name, orgsIds, continentId));
        }
        return list;
    }

    /**
     * Common base class for all the entities read from JSON file. The entities are {@link Country},
     * {@link Organization}, and {@link Continent}
     * 
     * @author Red Planet
     * 
     */
    abstract class BaseEntity {

        String name;
        long id;
        List<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

        private BaseEntity(long id, String name) {
            this.id = id;
            this.name = name;
        }

        public long getId() {
            return id;
        }

        // Insert all the data within a transaction
        abstract public List<ContentProviderOperation> getOperations();

        public String getName() {
            return name;
        }
    }

    public class Country extends BaseEntity {

        private List<Long> orgsIds;
        private long continentId;

        public Country(long id, String name, List<Long> orgsIds, long continentId) {
            super(id, name);
            this.orgsIds = new ArrayList<Long>();
            this.orgsIds.addAll(orgsIds);
            this.continentId = continentId;
        }

        @Override
        public List<ContentProviderOperation> getOperations() {
            ContentValues values = new ContentValues();
            // TODO: fill ContentValues with the data which will be inserted
            return operations;
        }

    }

    public class Organization extends BaseEntity {

        private Organization(long id, String name) {
            super(id, name);
        }

        @Override
        public List<ContentProviderOperation> getOperations() {
            ContentValues values = new ContentValues();
            // TODO: fill ContentValues with the data which will be inserted
            return operations;
        }
    }

    public class Continent extends BaseEntity {

        private Continent(long id, String name) {
            super(id, name);
        }

        @Override
        public List<ContentProviderOperation> getOperations() {
            ContentValues values = new ContentValues();
            // TODO: fill ContentValues with the data which will be inserted
            return operations;
        }
    }
}

JsonParserHelper.

This class gets arrays filled by readX methods and fills my database.

public class JsonParserHelper {

    public void insert(Context context, List<? extends BaseEntity> entities)
            throws OperationApplicationException, RemoteException {
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
        for (BaseEntity entity : entities) {
            operations.addAll(entity.getOperations());
        }
        context.getContentResolver().applyBatch(DatabaseProvider.AUTHORITY, operations);
    }

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top