Timothy_Goodman
Timothy_Goodman

Reputation: 421

JSON String to Java String

I have these JSON String:

{
    "Results": {
        "output1": {
            "type": "table",
            "value": {
                "ColumnNames": ["userId", "documentId", "Scored Labels", "Scored Probabilities"],
                "ColumnTypes": ["String", "String", "Boolean", "Double"],
                "Values": [["100213199594809000000", "1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI", "False", "0.375048756599426"], ["103097844766994000000", "1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs", "True", "0.753859758377075"]]
            }
        }
    }
}

And I want to have only the ColumnNames and the Values. I have tried it with something like this:

Map<String,Object> map = mapper.readValue(filename, Map.class);
String CN = (String) map.get("ColumnNames");

But then I get the following error:

Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: java.io.StringReader@64232b15; line: 1, column: 2]`

I've worked only few times with JSON. Can anybody help me here?

The best case for me would be something like this, which I've done in another case:

String uId = (String) attr.get("userId");

Is it possible?

So now I've done this:

I try it like this:

public class ClientPOJO {

    private String userId;
    private String documentId;


    public String getuserId() {
        return userId;
    }

    public void setuserId(String userId) {
        this.userId = userId;
    }

    public String getdocumentId() {
        return documentId;
    }

    public void setdocumentId(String documentId) {
        this.documentId = documentId;
    }

}

and then:

ObjectMapper mapper = new ObjectMapper();
                    ClientPOJO clientes= mapper.readValue(filename, ClientPOJO.class);

String uid = clientes.getuserId();

But now when I make a Prtinout I'll get the same error like before:

    Exception in thread "main" org.codehaus.jackson.JsonParseException: Unexpected character ('A' (code 65)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: java.io.StringReader@7a6eb29d; line: 1, column: 2]

Upvotes: 2

Views: 14739

Answers (4)

Gajender Singh
Gajender Singh

Reputation: 1313

Java- Convert JSON string into string / integer / Object

String jsonString = "{"username":"Gajender"}";
org.json.JSONObject jsonObj =new JSONObject(jsonString);
String name = (String) jsonObj.get("username").toString();

Upvotes: 2

skadya
skadya

Reputation: 4390

Below is an example to illustrate a generic approach to solve your problem ( based on Jackson library). You may like to enhance the solution to meet your all requirements.

Comments inlined.

package com.stackoverflow;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

// Junit class
public class TableDeserExample {
    // sample input
    String inputJson = "{\n" +
            "    \"Results\": {\n" +
            "        \"output1\": {\n" +
            "            \"type\": \"table\",\n" +
            "            \"value\": {\n" +
            "                \"ColumnNames\": [\"userId\", \"documentId\", \"Scored Labels\", \"Scored Probabilities\"],\n" +
            "                \"ColumnTypes\": [\"String\", \"String\", \"Boolean\", \"Double\"],\n" +
            "                \"Values\": [[\"100213199594809000000\", \"1Ktol-SWvAh8pnHG2O7HdPrfbEVZWX3Vf2YIPYXA_8gI\", \"False\", \"0.375048756599426\"], [\"103097844766994000000\", \"1jYsTPJH8gaIiATix9x34Ekcj31ifJMkPNb0RmxnuGxs\", \"True\", \"0.753859758377075\"]]\n"
            +
            "            }\n" +
            "        }\n" +
            "    }\n" +
            "}";

    // POJO to map the Json structure. You may want to make it generalize based
    // on field "type"
    // (https://github.com/FasterXML/jackson-docs/wiki/JacksonPolymorphicDeserialization)
    public static class Result {
        private String type;
        private TableResult value;

        public String getType() {
            return this.type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public void setValue(TableResult value) {
            this.value = value;
        }

        public TableResult getValue() {
            return this.value;
        }
    }

    // Pojo for table result
    public static class TableResult {
        private List<String> columnNames;
        private List<String> columnTypes;
        private List<Object[]> values;

        @JsonProperty("ColumnNames")
        public List<String> getColumnNames() {
            return this.columnNames;
        }

        public void setColumnNames(List<String> columnNames) {
            this.columnNames = columnNames;
        }

        @JsonProperty("ColumnTypes")
        public List<String> getColumnTypes() {
            return this.columnTypes;
        }

        public void setColumnTypes(List<String> columnTypes) {
            this.columnTypes = columnTypes;
        }

        @JsonProperty("Values")
        public List<Object[]> getValues() {
            return this.values;
        }

        public void setValues(List<Object[]> values) {
            this.values = values;
        }

    }

    // Top level Json POJO
    public static class ResultContainer {
        private Map<String, Result> results;

        @JsonProperty("Results")
        public Map<String, Result> getResults() {
            return this.results;
        }

        public void setResults(Map<String, Result> results) {
            this.results = results;
        }
    }

    // A contract to map the result "values" to the expected object
    public static interface ResultMapper<T> {
        T map(TableResult map, Object[] row);
    }

    // Basic implementation for mapping user object from json "values[i]" array
    public static class UserTableResultMapper implements ResultMapper<User> {

        @Override
        public User map(TableResult result, Object[] row) {
            User user = new User();
            // Here use any mapper logic based on column name
            // Retrieved from result object.
            // Below are for illustration only
            user.setId(String.valueOf(row[0]));
            user.setDocumentId(String.valueOf(row[1]));
            return user;
        }

    }

    // A result reader class
    public static class ResultReader<T> implements Iterable<T> {
        private TableResult result;
        private ResultMapper<T> mapper;

        public ResultReader(TableResult result, ResultMapper<T> mapper) {
            this.result = result;
            this.mapper = mapper;
        }

        @Override
        public Iterator<T> iterator() {
            final Iterator<Object[]> itr = result.getValues().iterator();
            return new Iterator<T>() {

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }

                @Override
                public T next() {
                    Object[] values = itr.next();
                    return mapper.map(result, values);
                }

                @Override
                public boolean hasNext() {
                    return itr.hasNext();
                }
            };
        };
    }

    public static class User {
        private String id;
        private String documentId;
        // and others

        public String getId() {
            return this.id;
        }

        public void setDocumentId(String documentId) {
            this.documentId = documentId;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getDocumentId() {
            return this.documentId;
        }

    }

    @Test
    public void simpleTest() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        ResultContainer file = mapper.readValue(inputJson, ResultContainer.class);
        Result result = file.getResults().get("output1");
        ResultReader<User> userResultReader = new ResultReader<>(result.getValue(), new UserTableResultMapper());
        for (User user : userResultReader) {
            System.out.println(user.getId() + " : " + user.getDocumentId());
        }
    }
}

Upvotes: 0

Manos Nikolaidis
Manos Nikolaidis

Reputation: 22244

Neither Jackson nor any other library will parse the Values array into objects with client data like your POJO. You can achieve this by getting the raw tree of data in this JSON and constructing objects by iterating over the Values array inside this tree. Assuming the order of ColumnNames is fixed then you can parse with Jackson like this:

final ObjectMapper mapper = new ObjectMapper();
final JsonNode tree = mapper.readTree(json);
final JsonNode values = tree.findValue("Values");

final List<ClientPOJO> clients = new ArrayList<>();
for (JsonNode node : values) {
    final ClientPOJO client = new ClientPOJO();
    client.setUserId(node.get(0).asText());
    client.setDocumentId(node.get(1).asText());
    client.setScoredLabels(node.get(2).asBoolean());
    client.setScoredProbabilities(node.get(3).asDouble());
    clients.add(client);
}

Docs for JsonNode. Basically with findValue you can get another node deep into the tree, with get you can get array elements by index and with asText etc you parse a value in JSON into the appropriate type in Java.

Since you seem to be flexible in choice of JSON parsing library I would suggest Jackson 2 from com.fasterxml instead of Jackson 1 from org.codehaus that you tried.

Upvotes: 0

TuyenNTA
TuyenNTA

Reputation: 1204

If you know exactly the structure of your json (like the json you have post) then you can using Gson to get your object like this:

JsonParser parser = new JsonParser();
JsonObject json = (JsonObject) parser.parse("your_json_string_here");
String column = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("ColumnNames").getAsJsonArray().toString();
String value = json.get("Results").getAsJsonObject().get("output1").getAsJsonObject().get("value").getAsJsonObject().get("Values").getAsJsonArray().toString();    
System.out.println(column);
System.out.println(value);

If you need some things more generic then you can parse your json string to a HashMap<String, Object> then using recursion to read the HashMap and get the value you want. Example (in my code, the type of Map will corresponding to a Json Object, type of List will corresponding to the Array in Json string):

Type type = new TypeToken<HashMap<String, Object>>() {}.getType();
Gson gson = new Gson();
HashMap<String, Object> map = gson.fromJson("your_json_string_here", type);
    for (String key : map.keySet()) {
        Object obj = map.get(key);
        if (obj instanceof List) {
            for (Object o : (List) obj) {
                if (o instanceof Map) {
                    loop((Map) o);
                } else {
                    System.out.println(key + " : " + o);
                }
            }
        } else if (obj instanceof Map) {
            loop((Map) obj);
        } else {
            System.out.println(key + " : " + obj);
        }
    }
}

private static void loop(Map<String, Object> map) {
    for (String key : map.keySet()) {
        Object obj = map.get(key);
        if (obj instanceof List) {
            for (Object o : (List) obj) {
                if (o instanceof Map) {
                    loop((Map) o);
                } else {
                    System.out.println(key + " : " + o);
                }
            }
        } else if (obj instanceof Map) {
            loop((Map) obj);
        } else {
            System.out.println(key + " : " + obj);
        }
    }
}

Upvotes: 0

Related Questions