How to deserialize only some fields in JSON? - java

I'm using Gson to extraxt some fields. By the way I don't want to create a class due to the fact that I need only one value in all JSON response. Here's my response:
{
"result": {
"name1": "value1",
"name2": "value2",
},
"wantedName": "wantedValue"
}
I need wantedValue but I don't want to create the entire class for deserialization. Is it possible to achieve this using Gson?

If you need one field only, use JSONObject.
import org.json.JSONException;
import org.json.JSONObject;
public class Main {
public static void main(String[] args) throws JSONException {
String str = "{" +
" \"result\": {" +
" \"name1\": \"value1\"," +
" \"name2\": \"value2\"," +
" }," +
" \"wantedName\": \"wantedValue\"" +
"}";
JSONObject jsonObject = new JSONObject(str);
System.out.println(jsonObject.getString("wantedName"));
}
Output:
wantedValue

If you don't have to use Gson, I would use https://github.com/douglascrockford/JSON-java. You can easily extract single fields. I could not find a way to do something this simple using Gson.
You would just do
String wantedName = new JSONObject(jsonString).getString("wantedName");

Can use just a portion of gson, using it just to parse the json:
Reader reader = /* create reader from source */
Streams.parse(new JsonReader(reader)).getAsJsonObject().get("wantedValue").getAsString();

Related

In Java how to easily get the value of a nested key from a JSON String / Object

I am using Java.
I have a string that I have converted to a JSON Object.
I want to extract the value of one of the Keys.
At the moment I am using this code:
String imageId = myJsonObject.getJSONObject("meta")
.getJSONObject("verification")
.getJSONObject("derivedData")
.getJSONArray("images")
.getJSONObject(0)
.getString("imageID");
This code works but surely there must be an easier way. In javascript I could access the value simply by writing this:
myJsonObject.meta.verification.derivedData.images[0].imageId
You may need to install library such as JsonPath to help you select values from a JSON object
An example to help understand better.
You can use external library Gson
Gson gson=new Gson();
/*You can convert to your DTO as well */
Map<Object,Object> map = gson.from(myJsonObject,Map.class);
Other way is using objectmapper example of fasterxml.
ObjectMapper objectMapper=new ObjectMapper();
/*You can convert to your DTO as well */
objectMapper.readValue(data, Map.class);
Try JsonNode by below step
String imageId= jsonNode.
findPath("meta")
.findPath("verification")
.findPath("derivedData")
.findPath("images")
.get (0).findPath ("imageID").asText ();
You need to use the 'Java API for JSON Binding' JSON-B instead of JSON-P. Using JSON-B you can serialize and deserialize between Java objects and data streams and access values of objects POJO style (similar to what you expect).
API details can be found here
A quick start tutorial can be found here and at many website only google search away..
I have created a small class for this purpose which can basically get value from json using a path only used google.gson
https://github.com/izeryab/JsonParser
Here is how to use this for getting nested value from json:
public class Main {
public static void main(String[] args) {
String json = "{\"data\":[{\"stuff\":[\n" + " { \"onetype\":[\n"
+ " {\"id\":1,\"name\":\"John Doe\"},\n" + " {\"id\":2,\"name\":\"Don Joeh\"}\n"
+ " ]},\n" + " {\"othertype\":[\n" + " {\"id\":2,\"company\":\"ACME\"}\n" + " ]}]\n"
+ "},{\"otherstuff\":[\n" + " {\"thing\":\n" + " [[1,42],[2,2]]\n" + " }]\n" + "}]}";
String name = JsonUtil.getJsonElementFromJsonStringUsingPath("data>0>stuff>0>onetype>0>name", json, ">").getAsString();
int id= JsonUtil.getJsonElementFromJsonStringUsingPath("data>0>stuff>0>onetype>0>id",json,">").getAsInt();
System.out.println("id : "+id);
System.out.println("name : "+name);
}
}
Corresponding JAVA DOCS:
https://izeryab.github.io/JsonParser/JsonUtil.html
You can use GSon, I've used it before (see below)
// Convert to a JSON object to print data
JsonParser jp = new JsonParser(); //from gson
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
JsonObject rootobj = root.getAsJsonObject(); //May be an array, may be an object.
JsonArray jsonDataArray = rootobj.getAsJsonArray("data");
JsonPrimitive totalJson = rootobj.getAsJsonPrimitive("total");
JsonPrimitive nextJson = rootobj.getAsJsonPrimitive("next");

Using Jackson to manually parse JSON

Is it possible to use Jackson library to manually parse JSON?
I.e. I don't want to use ObjectMapper and convert JSON to some object, but rather I want select some individual properties from JSON, like in XPath:
For example this is my JSON:
{
"person": {
"name": "Eric",
"surname": "Ericsson",
"address" {
"city": "LA",
"street": "..."
}
}
}
And all what I want is just to get Name and the City, for this cases I don't want introduce 2 new Java classes (Person and Address) and use them with ObjectMapper, but I'm just want to read this values like in xPath:
Pseudocode:
String name = myJson.get("person").get("name")
String city = myJson.get("person").get("address").get("city")
You can use the Jackson tree model and JsonNode#at(...) method which takes the Json Pointer expression as a parameter.
Here is an example:
public class JacksonJsonPointer {
static final String JSON = "{"
+ " \"person\": {"
+ " \"name\": \"Eric\","
+ " \"surname\": \"Ericsson\","
+ " \"address\": {"
+ " \"city\": \"LA\","
+ " \"street\": \"...\""
+ " }"
+ " }"
+ "}";
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
final JsonNode json = mapper.readTree(JSON);
System.out.println(json.at("/person/name"));
System.out.println(json.at("/person/address/city"));
}
}
Output:
"Eric"
"LA"
Yes Using Json parser you can parse your Json, Below is a sample example you can find more in jackson documentation
JsonParser jsonParser = new JsonFactory().createJsonParser(jsonStr);
while(jsonParser.nextToken() != JsonToken.END_OBJECT){
String name = jsonParser.getCurrentName();
if("name".equals(name)) {
jsonParser.nextToken();
System.out.println(jsonParser.getText());
}
if("surname".equals(name)) {
jsonParser.nextToken();
System.out.println(jsonParser.getText());
}
if("city".equals(name)) {
jsonParser.nextToken();
System.out.println(jsonParser.getText());
}
}

Convert JSON to hash map with Jackson- Java

Before this is marked as a duplicate please read the question (I did look at similar ones). Thank you.
For simplicity, assume I have JSON like this:
{
"clients" : [
{
"name" : "client 1",
"id" : 1
},
{
"name" : "client 2",
"id" : 2
}
],
"other" : {
"something" : ""
}
...
}
So I want to create a hash map of only the clients and their fields. The basic question is how would I go about doing this using Jackson methods for a single JSON array like clients? I've tried to look online but all of the examples that I have seen either don't use Jackson or only are for a single JSON object like so:
HashMap<String, String>[] values = new ObjectMapper().readValue(jsonString, new TypeReference<HashMap<String, String>[]>() {});
I've also seen Gson examples and I know I can do some string parsing magic:
jsonSting = jsonString.substring(jsonString.indexOf("["), (jsonString.indexOf("]")+1))
to get it in a format that I can use, but I want to try it with Jackson to avoid importing another library. Any ideas?
Rephrasing the question:
So if I only had a list of clients like so:
jsonString = [{"name" : "client 1","id" : 1},{"name" : "client 2","id" : 2}]
then I could just do:
HashMap[] values = new ObjectMapper().readValue(jsonString, new TypeReference[]>() {});
to get what I want. I am basically asking if there is a way using Jackson methods to get the jsonString above from the large JSON section on top. I know I can easily do it with this example with string parsing but there will be more complex situations in the future and string parsing is not really considered best practice
You can extract a part of the JSON tree using the Jackson tree model API and then convert it to an array of maps.
Here is an example:
public class JacksonReadPart {
public static final String JSON = "{\n" +
" \"clients\" : [\n" +
" {\n" +
" \"name\" : \"client 1\",\n" +
" \"id\" : 1\n" +
" },\n" +
" {\n" +
" \"name\" : \"client 2\",\n" +
" \"id\" : 2\n" +
" }\n" +
"],\n" +
" \"other\" : {\n" +
" \"something\" : \"\"\n" +
" }\n" +
"\n" +
"}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(JSON).path("clients");
// non type safe
Map<String, Object>[] clients = mapper.treeToValue(node, Map[].class);
System.out.println(Arrays.toString(clients));
// type safe
JsonParser parser = mapper.treeAsTokens(node);
clients = parser.readValueAs(new TypeReference<Map<String, Object>[]>() {});
System.out.println(Arrays.toString(clients));
}
}
Output:
[{name=client 1, id=1}, {name=client 2, id=2}]
[{name=client 1, id=1}, {name=client 2, id=2}]

Deserialization of sometimes string and sometimes object with Gson

I need to parse this type of JSON data to java objects:
{"id": 1, "blob": "example text"}
{"id": 2, "blob": {"to": 1234, "from": 4321, "name": "My_Name"}}
I am using Gson, and don't know how to get around this particular problem, of "blob" sometimes being a string and sometimes an object.
One solution to your problem is to write a TypeAdapter for your class, however if you have only cases like that in your example, you can achieve the same result letting Gson do the job for you using the most generic class you can for deserialization.
What I mean is shown in the below code.
package stackoverflow.questions.q19478087;
import com.google.gson.Gson;
public class Q19478087 {
public class Test {
public int id;
public Object blob;
#Override
public String toString() {
return "Test [id=" + id + ", blob=" + blob + "]";
}
}
public static void main(String[] str){
String json1 = "{\"id\": 1, \"blob\": \"example text\"}";
String json2 = "{\"id\": 2, \"blob\": {\"to\": 1234, \"from\": 4321, \"name\": \"My_Name\"}}";
Gson g = new Gson();
Test test1 = g.fromJson(json1, Test.class);
System.out.println("Test 1: "+ test1);
Test test2 = g.fromJson(json2, Test.class);
System.out.println("Test 2: "+ test2);
}
}
and this is my execution:
Test 1: Test [id=1, blob=example text]
Test 2: Test [id=2, blob={to=1234.0, from=4321.0, name=My_Name}]
In second case, blob will be deserialized as a LinkedTreeMap, so you can access its elements using ((Map) test2.blob).get("to") for example;
Let me know if it's enough or if you are interested also in the type adapter solution.
Try this one
Your POJO
class FromToName{
String to;
String from;
String name;
#Override
public String toString() {
return "FromToName [to=" + to + ", from=" + from + ", name=" + name
+ "]";
}
}
Your conversion code
String json ="{\"id\": 1, \"blob\": \"example text\"}";
//String json = "{\"id\": 2, \"blob\": {\"to\": 1234, \"from\": 4321, \"name\": \"My_Name\"}}";
Gson gson = new Gson();
JsonElement element = gson.fromJson (json, JsonElement.class);
JsonObject jsonObj = element.getAsJsonObject();
JsonElement id = jsonObj.get("id");
System.out.println(id);
if(jsonObj.get("blob") instanceof JsonPrimitive ){
JsonElement blob = jsonObj.get("blob");
System.out.println(blob);
}else{
FromToName blob = gson.fromJson (jsonObj.get("blob"), FromToName.class);
System.out.println(blob);
}
If you have any doubt in this let me know
Take that as a JSON Element and then use isMethods() to figure out the type at runtime.
Documentation
JsonParser jp = new JsonParser();
JsonElement ele = jp.parse(jsonString).getAsJsonObject().get("blob");;
if (ele.isJsonObject()) {
//do related stuff here
} else if (ele.isJsonArray()) {
//do related stuff here
}

JSON String to Java object using GSON

I am trying to parse json to java.
I have the following string that is valid json according to jsonlint.com
private final static String LOC_JSON =
"["
+"{"
+" \"lat1\": 39.737567,"
+" \"lat2\": 32.7801399,"
+" \"long1\": -104.98471790000002,"
+" \"long2\": -96.80045109999998"
+"},"
+" ["
+" {"
+" \"lat\": {"
+" \"b\": 38.88368709500021,"
+" \"d\": 40.620468491667026"
+" },"
+" \"long\": {"
+" \"b\": -105.75306170749764,"
+" \"d\": -104.675854661387"
+" }"
+" }"
+" ]"
+"]";
I am trying to parse it into an object and I get the following error.
"Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2"
Gson gson = new Gson();
BoxSearch b = gson.fromJson( LOC_JSON, BoxSearch.class );
BoxSearch consists of this.
private Number lat1;
private Number lat2;
private Number long1;
private Number long2;
private Boxes[] boxes;
Boxes is a Latitude object and a Longitude object which are both defined identical.
private String b;
private String d;
I can parse the higher level attributes (lat1,lat2,long1 and long2) into a more simple BoxSearch object that only has those 4 attributes. The trouble comes when the json and the object are more complex. Is it even possible to do what I am trying?
I hope I have provided enough information to get some help. I would be happy to provide more info or even a test project if need be. I am running this as a junit test.
Thanks.
Gson gson = new Gson();
gson.fromJson(jsonStr,YourClass.class);
very easy.
The reason for the error is that your JSON at the top level is an array, not an object. That is covered by GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?.
However, the solution there won't work for your JSON because you have an array of mixed types (an object and an array) rather than an array of a single type of object. For that you're going to have to write a custom deserializer (See The section of the Gson user's guide that covers this) or use Gson's JsonParser class directly and extract the data from the parse tree.
Edit from comments above:
If you're the one creating the JSON, it looks like what you want is an array of BoxSearch objects?
Based on your Java BoxSearch class, you'd need JSON structured like:
[
{
"lat1" : 39.737567,
"lat2" : 32.7801399,
"long1" : -104.98471790000002,
"long2" : -96.80045109999998,
"boxes" : [
{
"lat": {
"b": 38.88368709500021,
"d": 40.620468491667026
},
"long": {
"b": -105.75306170749764,
"d": -104.675854661387
}
}
]
}
]
However, the way you have Boxes class defined won't work for that. (Did you mean to have an array of them?). As-is it would need to look like:
class Boxes {
Box lat;
#SerializedName("long")
Box lon;
}
class Box {
String b;
String d;
}
Now you have an array containing one type of object (BoxSearch) which you could deserialize with:
Type collectionType = new TypeToken<Collection<BoxSearch>>(){}.getType();
Collection<BoxSearch> boxSearchCollection = gson.fromJson(json, collectionType);
If you really don't need an array of these, get rid of the outer array and simply do:
gson.fromJson(json, BoxSearch.class);

Categories

Resources