What is the best way to convert a JSON code as this:
{
"data" :
{
"field1" : "value1",
"field2" : "value2"
}
}
in a Java Map in which one the keys are (field1, field2) and the values for those fields are (value1, value2).
Any ideas? Should I use Json-lib for that? Or better if I write my own parser?
I hope you were joking about writing your own parser. :-)
For such a simple mapping, most tools from http://json.org (section java) would work.
For one of them (Jackson https://github.com/FasterXML/jackson-databind/#5-minute-tutorial-streaming-parser-generator), you'd do:
Map<String,Object> result =
new ObjectMapper().readValue(JSON_SOURCE, HashMap.class);
(where JSON_SOURCE is a File, input stream, reader, or json content String)
Using the GSON library:
import com.google.gson.Gson;
import com.google.common.reflect.TypeToken;
import java.lang.reclect.Type;
Use the following code:
Type mapType = new TypeToken<Map<String, Map>>(){}.getType();
Map<String, String[]> son = new Gson().fromJson(easyString, mapType);
I like google gson library.
When you don't know structure of json. You can use
JsonElement root = new JsonParser().parse(jsonString);
and then you can work with json. e.g. how to get "value1" from your gson:
String value1 = root.getAsJsonObject().get("data").getAsJsonObject().get("field1").getAsString();
Use JSON lib E.g. http://www.json.org/java/
// Assume you have a Map<String, String> in JSONObject jdata
#SuppressWarnings("unchecked")
Iterator<String> nameItr = jdata.keys();
Map<String, String> outMap = new HashMap<String, String>();
while(nameItr.hasNext()) {
String name = nameItr.next();
outMap.put(name, jdata.getString(name));
}
My post could be helpful for others, so imagine you have a map with a specific object in values, something like that:
{
"shopping_list":{
"996386":{
"id":996386,
"label":"My 1st shopping list",
"current":true,
"nb_reference":6
},
"888540":{
"id":888540,
"label":"My 2nd shopping list",
"current":false,
"nb_reference":2
}
}
}
To parse this JSON file with GSON library, it's easy :
if your project is mavenized
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.3.1</version>
</dependency>
Then use this snippet :
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
//Read the JSON file
JsonElement root = new JsonParser().parse(new FileReader("/path/to/the/json/file/in/your/file/system.json"));
//Get the content of the first map
JsonObject object = root.getAsJsonObject().get("shopping_list").getAsJsonObject();
//Iterate over this map
Gson gson = new Gson();
for (Entry<String, JsonElement> entry : object.entrySet()) {
ShoppingList shoppingList = gson.fromJson(entry.getValue(), ShoppingList.class);
System.out.println(shoppingList.getLabel());
}
The corresponding POJO should be something like that :
public class ShoppingList {
int id;
String label;
boolean current;
int nb_reference;
//Setters & Getters !!!!!
}
Hope it helps !
With google's Gson 2.7 (probably earlier versions too, but I tested 2.7) it's as simple as:
Map map = gson.fromJson(json, Map.class);
Which returns a Map of type class com.google.gson.internal.LinkedTreeMap and works recursively on nested objects.
This way its works like a Map...
JSONObject fieldsJson = new JSONObject(json);
String value = fieldsJson.getString(key);
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>1.1</version>
</dependency>
I do it this way. It's Simple.
import java.util.Map;
import org.json.JSONObject;
import com.google.gson.Gson;
public class Main {
public static void main(String[] args) {
JSONObject jsonObj = new JSONObject("{ \"f1\":\"v1\"}");
#SuppressWarnings("unchecked")
Map<String, String> map = new Gson().fromJson(jsonObj.toString(),Map.class);
System.out.println(map);
}
}
java.lang.reflect.Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Gson gson = new Gson();
Map<String, Object> categoryicons = gson.fromJson(json, mapType );
If you're using org.json, JSONObject has a method toMap().
You can easily do:
Map<String, Object> myMap = myJsonObject.toMap();
The JsonTools library is very complete. It can be found at Github.
Try this code:
public static Map<String, Object> convertJsonIntoMap(String jsonFile) {
Map<String, Object> map = new HashMap<>();
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
mapper.readValue(jsonFile, new TypeReference<Map<String, Object>>() {
});
map = mapper.readValue(jsonFile, new TypeReference<Map<String, String>>() {
});
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
One more alternative is json-simple which can be found in Maven Central:
(JSONObject)JSONValue.parse(someString); //JSONObject is actually a Map.
The artifact is 24kbytes, doesn't have other runtime dependencies.
If you need pure Java without any dependencies, you can use build in Nashorn API from Java 8. It is deprecated in Java 11.
This is working for me:
...
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
...
public class JsonUtils {
public static Map parseJSON(String json) throws ScriptException {
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine engine = sem.getEngineByName("javascript");
String script = "Java.asJSONCompatible(" + json + ")";
Object result = engine.eval(script);
return (Map) result;
}
}
Sample usage
JSON:
{
"data":[
{"id":1,"username":"bruce"},
{"id":2,"username":"clark"},
{"id":3,"username":"diana"}
]
}
Code:
...
import jdk.nashorn.internal.runtime.JSONListAdapter;
...
public static List<String> getUsernamesFromJson(Map json) {
List<String> result = new LinkedList<>();
JSONListAdapter data = (JSONListAdapter) json.get("data");
for(Object obj : data) {
Map map = (Map) obj;
result.add((String) map.get("username"));
}
return result;
}
JSON to Map always gonna be a string/object data type. i have GSON lib from google.
Gson library working with string not for complex objects you need to do something else
Try this piece of code, it worked for me,
Map<String, Object> retMap = new Gson().fromJson(
myJsonString, new TypeToken<HashMap<String, Object>>() {}.getType()
);
import net.sf.json.JSONObject
JSONObject.fromObject(yourJsonString).toMap
Underscore-java library can convert json string to hash map. I am the maintainer of the project.
Code example:
import com.github.underscore.U;
import java.util.*;
public class Main {
#SuppressWarnings("unchecked")
public static void main(String[] args) {
String json = "{"
+ " \"data\" :"
+ " {"
+ " \"field1\" : \"value1\","
+ " \"field2\" : \"value2\""
+ " }"
+ "}";
Map<String, Object> data = (Map) U.get((Map<String, Object>) U.fromJson(json), "data");
System.out.println(data);
// {field1=value1, field2=value2}
}
}
JSON to Map always gonna be a string/object data type. i haved GSON lib from google.
works very well and JDK 1.5 is the min requirement.
Related
I am trying to map a JSON file into Java objects using Jackson library. This json file is a multi-level file that can be found here:
https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson
It is the list of earthquakes that happened in the last 30 days in the US.
Here is the structure of this son file: https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php
Now, I wrote a Java program that is reading fields from this file, specifically I am trying to access the field which is under features -> properties -> place (e.g. from the original file "place":"17km NW of Pinnacles, CA")). When I get to the properties field I can read it as a LinkedHashMap, but the next level, so the keys and values of this LinkedHashMap are being read as Strings:
for example this is one of the values : {type=Point, coordinates=[-121.2743333, 36.6375, 8.61]}
I WANT TO READ THESE VALUES AS ANOTHER OBJECT (NOT STRING, MAP MAYBE?) SO I COULD EXTRACT FURTHER DATA FROM IT.
Here is my class:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.ObjectMapper;
#JsonIgnoreProperties(ignoreUnknown = true)
public class ReadJSONFile {
private StringBuffer stringBuffer = new StringBuffer();
public void convert_json_to_java() throws Exception {
String url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in .readLine()) != null) {
stringBuffer.append(inputLine);
stringBuffer.append("\n");
} in.close();
}
#SuppressWarnings("unchecked")
public void map_to_object() throws Exception {
ObjectMapper om = new ObjectMapper();
//ignore fields that are not formatted properly
om.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Map<Object, Object> resultMap = om.readValue(stringBuffer.toString(), Map.class);
ArrayList<Object> featuresArrayList = (ArrayList<Object>) resultMap.get("features");
for(Object o : featuresArrayList) {
LinkedHashMap<Object, Object> propertiesMap = (LinkedHashMap<Object, Object>) o;
for(Map.Entry<Object, Object> entry : propertiesMap.entrySet()) {
//HERE IS THE PROBLEM, THE VALUES OF THIS MAP (SECOND OBJECT) IS BEING READ AS A STRING
//WHILE SOME VALUES ARE NOT A STRING:
//e.g. {type=Point, coordinates=[-121.2743333, 36.6375, 8.61]}
//AND I WANT TO READ IT AS A MAP OR ANY OTHER OBJECT THAT WOULD ALLOW ME TO ACCESS THE DATA
String propertiesMapValues = entry.getValue().toString();
}
}
}
}
Main.java
public class Main {
public static void main(String[] args) throws Exception {
ReadJSONFile rjf = new ReadJSONFile();
rjf.convert_json_to_java();
rjf.map_to_object();
}
}
Maven dependency: https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl
When I try casting this last object to anything else than String, the program gives me exception (can't cast String to another object). Did I do something wrong? Can someone tell me what can I do to access those fields without modifying Strings (e.g. splitting them into arrays etc.)?
Actually your code works but it could be a bit simplified. The method convert_json_to_java is unnecessary, you can pass the URL directly to the ObjectMapper.
The values in the map are not read as Strings, but you are converting them to Strings by calling toString(), which is defined for all objects. Acctual types can be Map, List, String, Integer etc., depending on the JSON content. Working with a generic map is indeed a bit annoying, so I would suggest you converting values to structured objects. GeoJSON is an open standard, so there are open-source libraries facilitating using it, e.g. geojson-jackson.
You would need to add a maven dependency:
<dependency>
<groupId>de.grundid.opendatalab</groupId>
<artifactId>geojson-jackson</artifactId>
<version>1.8.1</version>
</dependency>
Then the program could look something like:
import org.geojson.*
// ...
public class ReadJSONFile {
ObjectMapper om = new ObjectMapper();
public void mapToObject(String url) throws Exception {
Map<String, Object> resultMap = om.readValue(new URL(url), new TypeReference<Map<String, Object>>() {});
List<Feature> features = om.convertValue(resultMap.get("features"), new TypeReference<List<Feature>>() {});
for(Feature f : features) {
// Write the feature to the console to see how it looks like
System.out.println(om.writeValueAsString(f));
// Extract properties
Map<String,Object> properties = f.getProperties();
// ....
// Extract geometry
GeoJsonObject geometry = f.getGeometry();
if(geometry instanceof Point) {
Point p = (Point) geometry;
// do something with the point
} else if(geometry instanceof LineString) {
LineString mls = (LineString) geometry;
// ...
} else if(geometry instanceof MultiLineString) {
MultiLineString mls = (MultiLineString) geometry;
// ...
} else if(geometry instanceof MultiPoint) {
MultiPoint mp = (MultiPoint) geometry;
// ...
} else if(geometry instanceof Polygon) {
Polygon pl = (Polygon) geometry;
// ...
} else if(geometry != null) {
throw new RuntimeException("Unhandled geometry type: " + geometry.getClass().getName());
}
}
}
public static void main(String[] args) throws Exception {
ReadJSONFile rjf = new ReadJSONFile();
rjf.mapToObject("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson");
}
}
I am trying to read a json file and convert it to the jsonObject and when I searched on how to do it, I came across the method to user
JSONParser parser= new JSONParse();
But the version of org.json I am using in the code is "20180803". It does not contain JSONParser. Has it been removed from the org.json package? If so what is the new class or method that I could use to read a json file and convert it to a json object.
My dependency is given below :
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
Hi you can use simple JSON. You just need to add in your pom.xml file:
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</dependency>
Sample code
public static JSONObject convertJsonStingToJson(String jsonString) {
JSONParser parser = new JSONParser();
return json = (JSONObject) parser.parse(jsonString);
}
org.json library has very simple API which does not have JSONParser but has JSONTokener. We can construct JSONObject or JSONArray directly from String:
import org.json.JSONArray;
import org.json.JSONObject;
public class JsonApp {
public static void main(String[] args) {
// JSON Object
String object = "{\"p1\":\"v1\", \"p2\":2}";
JSONObject jsonObject = new JSONObject(object);
System.out.println(jsonObject);
// JSON Array
String array = "[{\"p1\":\"v1\", \"p2\":2}]";
JSONArray jsonArray = new JSONArray(array);
System.out.println(jsonArray);
}
}
Above code prints:
{"p1":"v1", "p2":2}
[{"p1":"v1","p2":2}]
You need to notice that it depends from JSON payload which class to use: if JSON starts from { use JSONObject, if from [ - use JSONArray. In other case JSON payload is invalid.
As it mentioned in other answers, if you can you should definitely use Jackson or Gson
Add following dependency in build file
//json processing
implementation("com.fasterxml.jackson.core:jackson-core:2.9.8")
implementation("com.fasterxml.jackson.core:jackson-annotations:2.9.8")
implementation("com.fasterxml.jackson.core:jackson-databind:2.9.8")
a.json file
{
"a": "b"
}
code:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.FileInputStream;
import java.io.InputStream;
public class App {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("a.json");
JsonNode obj = objectMapper.readTree(input);
System.out.println(obj.get("a")); // "b"
}
}
The short answer to your question is: No, it was not removed, because it never existed.
I think you are mentioning a library, and trying to use another one. Anyway, if you really want to use org.json, you can find how here
JSONObject jsonObject = new JSONObject(instanceOfClass1);
String myJson = jsonObject.toString();
I have a very large JSON file in the following format:
[{"fullname": "name1", "id": "123"}, {"fullname": "name2", "id": "245"}, {"fullname": "name3", "id": "256"}]
It looks like a JSONArray. All the records are written in the same line.
Can you help me how can I parse this file using Java. I want to read each JSON object and display all the fullname and ids. Below is my attempt, but my code is not working:
import org.apache.commons.lang3.StringEscapeUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSONFileReaderDriver {
public static void main(String[] args) throws FileNotFoundException,
IOException, ParseException
{
String filename="Aarau";
String src="C:\\"+filename+".json";
JSONParser parser = new JSONParser();
JSONObject obj;
try
{
BufferedReader br=new BufferedReader (new FileReader(src));
obj = (JSONObject) new JSONParser().parse(row);
String fullname=obj.get("fullname");
String id=obj.get("id");
System.out.println ("fullname: "+fullname+" id: "+id);
}catch(Exception e)
{e.printStackTrace();}
br.close();
}
}
Make your life easy and use an ObjectMapper.
This way you simply define a Pojo with the same properties as you json object.
In you case you need a Pojo that looks like this:
public class Person{
private String fullname;
private int id;
public Person(String fullname, int id) {
this.fullname = fullname;
this.id = id;
}
public String getFullname() {
return fullname;
}
public int getId() {
return id;
}
}
With that you only need to do:
ObjectMapper objectMapper = new ObjectMapper();
List<Person> persons = objectMapper.readValue(myInputStream, TypeFactory.defaultInstance().constructCollectionType(List.class, Person.class));
This is a hassle free and type safe approach.
Dependencies needed:
https://github.com/FasterXML/jackson-databind
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
you can use Json.simple java api , below is code that can helpful to you
byte[] bFile = Files.readAllBytes(new File("C:/xyz.json").toPath());
JSONArray root = (JSONArray) JSONValue.parseWithException(bFile);
JSONObject rootObj = (JSONObject) root.get(0);
You can get values from JSONObject based on key , it also depends on format of your json as there could be nested json data. So you have to extract data accordingly . Apart from this you can use jackson parser api or GSON as well.
Okay folks...just solved my problem. I am posting the solution in case someone runs into the same issue again, can use my solution. My solution is partly motivated by Rahul Rabhadiya. Thanks, dude.
try{
row=br.readLine();
JSONArray root = (JSONArray) JSONValue.parseWithException(row);
for (int i=0;i<root.size();i++)
{
JSONObject rootObj = (JSONObject) root.get(i);
String fullname=(String) rootObj.get("fullname");
System.out.println (fullname);
}
}catch(Exception e)
{
e.printStackTrace();
}
Your json is a JSONArray, so when you are parsing it, you need to parse it as a JSONArray.
JSONParser jsonParser = new JSONParser();
JSONArray a = (JSONArray) jsonParser.parse(new FileReader(src));
for (Object o : a) {
// access your object here.
}
I would suggest going with Jackson, in particular the Jackson Streaming API which is perfect for parsing large arrays like this.
See this answer: https://stackoverflow.com/a/24838392/3765428
I'm having a hash map with set of keys and values.
I would like to convert it to a json format and print the entire string.
I don't like to create a file and need to dynamically print the string in the screen. i'm using fasterxml api. (http://wiki.fasterxml.com/JacksonInFiveMinutes)
Please let me know how to do it.
Please look at the following:
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
public static void main(String[] args) throws JsonProcessingException {
Map<String, Object> map = new HashMap<String, Object>();
map.put( "language", "Java" );
map.put( "year", 2016 );
map.put( "isObjectOriented", true );
ObjectMapper mapper = new ObjectMapper();
String jsonInString = mapper.writeValueAsString(map);
System.out.printf( "JSON: %s", jsonInString );
}
}
I have used following jars:
jackson-core-2.7.4.jar, jackson-databind-2.7.4.jar and jackson-annotations-2.7.4.jar. Hope it helps.
I have the following JSON snippets:
{ "randomlygeneratedKeyname0" : "some-value",
"randomlygeneratedKeyname1": {
"randomlygeneratedKeyname2" : {
"randomlygeneratedKeyname3": "some-value",
"randomlygeneratedKeyname4": "some-value"
},
"randomlygeneratedKeyname5": {
"randomlygeneratedKeyname6": "some-value",
"randomlygeneratedKeyname7": "some-value"
}
}
}
Notes that I don't know the name of randomlygeneratedKeyname and their naming convention is inconsistent so I could not create my corresponding Java field/variable names.
How do I (de)serialize it in GSON?
Thanks in advance for your help.
I'm pleased to report that with GSON 2.0 supports default maps and lists without effort. Deserialize like this:
Object o = new Gson().fromJson(json, Object.class);
The result will be a Map with String keys and either String or Map values.
Serialize that map back to JSON like this:
String json = new Gson().toJson(o);
We hope to release GSON 2.0 in October 2012. You can get it early from GSON SVN.
Code dump solution:
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args) throws Exception
{
Type mapStringObjectType = new TypeToken<Map<String, Object>>() {}.getType();
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(mapStringObjectType, new RandomMapKeysAdapter());
Gson gson = gsonBuilder.create();
Map<String, Object> map = gson.fromJson(new FileReader("input.json"), mapStringObjectType);
System.out.println(map);
}
}
class RandomMapKeysAdapter implements JsonDeserializer<Map<String, Object>>
{
#Override
public Map<String, Object> deserialize(JsonElement json, Type unused, JsonDeserializationContext context)
throws JsonParseException
{
// if not handling primitives, nulls and arrays, then just
if (!json.isJsonObject()) throw new JsonParseException("some meaningful message");
Map<String, Object> result = new HashMap<String, Object> ();
JsonObject jsonObject = json.getAsJsonObject();
for (Entry<String, JsonElement> entry : jsonObject.entrySet())
{
String key = entry.getKey();
JsonElement element = entry.getValue();
if (element.isJsonPrimitive())
{
result.put(key, element.getAsString());
}
else if (element.isJsonObject())
{
result.put(key, context.deserialize(element, unused));
}
// if not handling nulls and arrays
else
{
throw new JsonParseException("some meaningful message");
}
}
return result;
}
}