Map GeoJSON to Java with Jackson - java

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");
}
}

Related

How can I use JsonParser (javax.json.stream.JsonParser) twice

I need to use a JsonParser twice, once to validate the format of my JsonStream by the json schema given..., then I need to contruct my object 'Product'.
The problem is that if I use the parser once, I cannot re-use it a second time. It's like it loses its data values .
Here is my Original code where I construct my Product object using the parser.. :
import javax.json.bind.serializer.DeserializationContext;
import javax.json.bind.serializer.JsonbDeserializer;
import javax.json.stream.JsonParser;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class ProductDeserializer implements JsonbDeserializer<Product>
{
#Override
public Product deserialize(final JsonParser parser, final DeserializationContext ctx, final Type rtType)
{
Product product = new Product();
while (parser.hasNext())
{
JsonParser.Event event = parser.next();
if (event == JsonParser.Event.KEY_NAME && parser.getString().equals("productNumber"))
{
parser.next();
product.setProductNumber(parser.getString());
This works fine But I need to include this validation of the json format first..:
ObjectMapper objectMapper = new ObjectMapper();
JsonSchemaFactory schemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V201909);
String schemaStream = "My json schema here..";
JsonNode json = null;
try
{
json = objectMapper.readTree(parser.getObject().toString());
}
catch (JsonProcessingException eParam)
{
eParam.printStackTrace();
}
JsonSchema schema = schemaFactory.getSchema(schemaStream);
Set<ValidationMessage> validationResult = schema.validate(json);
if (validationResult.isEmpty()) {
System.out.println("no validation errors ");
} else {
System.out.println("There are validation errors ");
}
So if I try to include this part then the contruction of my Product Object will not work anymore and the Product will be null..
So my question is how can I use the parser twice in the same method ..
Thanks a lot in advance..

Converting myClass.ChatColor objects to and from .json files result in undesired leading `Â` characters

I'm storing ChatColor objects stored in a class object. After successfully converting them to json using the Gson api, I want to be able to instantiate ChatColor objects in memory from this stored json file.
Using the code below, I get ChatColor objects who's toString methods return §6. they should be returning the same but minus the leading  character
To make this question easier to read I've reduced the examples down to a single ChatColor object per Theme object.
Theme.java
package core.data.objects;
import java.util.Map;
import net.md_5.bungee.api.ChatColor;
public class Theme {
private ChatColor primary, secondary, tertiary, clear, faded, succeed, fail;
public Theme(Map<String, ChatColor> thisMap) {
this.primary = thisMap.get("primary");
}
public ChatColor getPrimary() { return primary; }
public void setPrimary(ChatColor primary) { this.primary = primary; }
}
ThemeManager.java
package core.data;
import core.data.objects.Theme;
import java.io.*;
import java.util.Map;
import java.util.HashMap;
import com.google.gson.Gson;
import net.md_5.bungee.api.ChatColor;
public class ThemeManager {
public static Theme currentTheme;
public static void load() throws IOException {
try {
currentTheme = getThemeFromJSON(FileManager.defaultThemeFile);
System.out.println(ChatColor.GOLD);
System.out.println(currentTheme.getPrimary());
} catch (Exception e) {
currentTheme = createDefaultTheme();
System.out.println("WARN getThemeFromJSON Exception");
throw new IOException(e.getMessage());
}
}
public static Theme createDefaultTheme() {
Map<String, ChatColor> thisMap = new HashMap<>();
thisMap.putIfAbsent("primary", ChatColor.GOLD);
return new Theme(thisMap);
}
public static void writeThemeToJSON(Theme thisTheme, File thisFile) throws IOException {
Gson gson = new Gson();
Writer writer = new FileWriter(thisFile, false);
gson.toJson(thisTheme, writer);
writer.flush(); writer.close();
}
public static Theme getThemeFromJSON(File thisFile) throws FileNotFoundException {
Gson gson = new Gson();
Reader reader = new FileReader(thisFile);
return gson.fromJson(reader, Theme.class);
}
}
Console output of ThemeManager.load()
[20:20:56 INFO]: §6
[20:20:56 INFO]: §6
Example of saved .json file
{
"primary": {
"toString": "§6",
"name": "gold",
"ordinal": 6,
"color": {
"value": -22016,
"falpha": 0.0
}
}
}
The  comes out of nowhere!
Solution credit: #dave_thompson_085
The project (and the .json file) are encoded in UTF-8, but I was not reading the file using UTF-8 encoding. Apparently that is not the default encoding of a FileReader object.
By changing this:
public static Theme getThemeFromJSON(File thisFile) throws FileNotFoundException {
Gson gson = new Gson();
Reader reader = new FileReader(thisFile);
return gson.fromJson(reader, Theme.class);
}
to this:
public static Theme getThemeFromJSON(File thisFile) throws FileNotFoundException {
Gson gson = new Gson();
Reader reader = new InputStreamReader (
new FileInputStream (thisFile), StandardCharsets.UTF_8);
return gson.fromJson(reader, Theme.class);
}
, the stdout lines from ThemeManager.load() are now both showing §6 as expected.
However, note that when using aThemeObject.getPrimary(), the returned ChatColor object was not able to be used in place of regular calls to ChatColor.COLOR.
Trying to do so would simply result in "null" appearing in the displayed text in-game.
To fix this, I modified the get methods to:
public ChatColor getPrimary() {
return ChatColor.getByChar(primary.toString().charAt(1));
}
char at index 1 is the color code used by the getByChar method to return a clone chatcolor object.
This will prevent using custom falpha values and custom color values in the theme.json file, but ensures the resulting ChatColor object from calling Theme.getPrimary() can always be used in place of a regular call to ChatColor.COLOR

How do I read a data from a JSON file with high efficiency in Java with Jackson?

I store all static data in the JSON file. This JSON file has up to 1000 rows. How to get the desired data without storing all rows as ArrayList?
My code, I'm using right now and I want to increase its efficiency.
List<Colors> colorsList = new ObjectMapper().readValue(resource.getFile(), new TypeReference<Colors>() {});
for(int i=0; i<colorsList.size(); i++){
if(colorsList.get(i).getColor.equals("Blue")){
return colorsList.get(i).getCode();
}
}
Is it possible? My goal is to increase efficiency without using ArrayList. Is there a way to make the code like this?
Colors colors = new ObjectMapper().readValue(..."Blue"...);
return colors.getCode();
Resource.json
[
...
{
"color":"Blue",
"code":["012","0324","15478","7412"]
},
{
"color":"Red",
"code":["145","001","1","7879","123984","89"]
},
{
"color":"White",
"code":["7","11","89","404"]
}
...
]
Colors.java
class Colors {
private String color;
private List<String> code;
public Colors() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public List<String> getCode() {
return code;
}
public void setCode(List<String> code) {
this.code = code;
}
#Override
public String toString() {
return "Colors{" +
"color='" + color + '\'' +
", code=" + code +
'}';
}
}
Creating POJO classes in this case is a wasting because we do not use the whole result List<Colors> but only one internal property. To avoid this we can use native JsonNode and ArrayNode data types. We can read JSON using readTree method, iterate over array, find given object and finally convert internal code array. It could look like below:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
ArrayNode rootArray = (ArrayNode) mapper.readTree(jsonFile);
int size = rootArray.size();
for (int i = 0; i < size; i++) {
JsonNode jsonNode = rootArray.get(i);
if (jsonNode.get("color").asText().equals("Blue")) {
Iterator<JsonNode> codesIterator = jsonNode.get("code").elements();
List<String> codes = new ArrayList<>();
codesIterator.forEachRemaining(n -> codes.add(n.asText()));
System.out.println(codes);
break;
}
}
}
}
Above code prints:
[012, 0324, 15478, 7412]
Downside of this solution is we load the whole JSON to memory which could be a problem for us. Let's try to use Streaming API to do that. It is a bit difficult to use and you must know how your JSON payload is constructed but it is the fastest way to get code array using Jackson. Below implementation is naive and does not handle all possibilities so you should not rely on it:
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
System.out.println(getBlueCodes(jsonFile));
}
private static List<String> getBlueCodes(File jsonFile) throws IOException {
try (JsonParser parser = new JsonFactory().createParser(jsonFile)) {
while (parser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = parser.getCurrentName();
// Find color property
if ("color".equals(fieldName)) {
parser.nextToken();
// Find Blue color
if (parser.getText().equals("Blue")) {
// skip everything until start of the array
while (parser.nextToken() != JsonToken.START_ARRAY) ;
List<String> codes = new ArrayList<>();
while (parser.nextToken() != JsonToken.END_ARRAY) {
codes.add(parser.getText());
}
return codes;
} else {
// skip current object because it is not `Blue`
while (parser.nextToken() != JsonToken.END_OBJECT) ;
}
}
}
}
return Collections.emptyList();
}
}
Above code prints:
[012, 0324, 15478, 7412]
At the end I need to mention about JsonPath solution which also can be good if you can use other library:
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
import java.io.File;
import java.util.List;
import java.util.stream.Collectors;
public class JsonPathApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
JSONArray array = JsonPath.read(jsonFile, "$[?(#.color == 'Blue')].code");
JSONArray jsonCodes = (JSONArray)array.get(0);
List<String> codes = jsonCodes.stream()
.map(Object::toString).collect(Collectors.toList());
System.out.println(codes);
}
}
Above code prints:
[012, 0324, 15478, 7412]
You can use DSM stream parsing library for memory, CPU efficiency and fast development. DSM uses YAML based mapping file and reads the whole data only once.
Here is the solution of your question:
Mapping File:
params:
colorsToFilter: ['Blue','Red'] # parameteres can be passed programmatically
result:
type: array
path: /.*colors # path is regex
filter: params.colorsToFilter.contains(self.data.color) # select only color that exist in colorsToFilter list
fields:
color:
code:
type: array
Usage of DSM to parse json:
DSM dsm = new DSMBuilder(new File("path/maping.yaml")).create(Colors.class);
List<Colors> object = (List<Colors>) dsm.toObject(jsonData);
System.out.println(object);
Output:
[Colors{color='Blue', code=[012, 0324, 15478, 7412]}, Colors{color='Red', code=[145, 001, 1, 7879, 123984, 89]}]

Recursive method to return different objects stored as JSON files

I found this answer and I think it applies, but with a little twist.
How to return multiple objects from a Java method?
I have two JSON formatted files using the YML subset, one of which is a list of devices, and the other is a file that lists the attributes of a particular type of device.
The choice of dividing up the list of Device instances into one file and the attributes in another file is to allow the Device manufacturer to change the attributes without having to go back and rewrite/recompile hard coded attributes.
In any case, I could use two different calls to the JSONParser and then add the list of attributes to the Device object in the end, but that solution seems like a waste of code since, except for the inner part of the while loop where the values are set, they do exactly the same thing.
I thought something like a Ruby-ish Yield might do the trick in the inner loop, but not sure if this exists in Java.
So, without much further ado, here is the code:
// Import the json simple parser, used to read configuration files
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.*;
public class LoadJson {
private String path = "";
private String fileType = "";
//public LoadJson(String path, String fileType){
//this.path = path;
//this.fileType = fileType;
//}
public static Device openJSON(String fileType, String deviceName) {
JSONParser parser = new JSONParser();
Device myDevice = new Device();
ContainerFactory containerFactory = new ContainerFactory(){
public List creatArrayContainer() {
return new LinkedList();
}
public Map createObjectContainer() {
return new LinkedHashMap();
}
};
try {
File appBase = new File("."); //current directory
String path = appBase.getAbsolutePath();
System.out.println(path);
Map obj = (Map)parser.parse(new FileReader(path+fileType),containerFactory);
Iterator iter = obj.entrySet().iterator();
//Iterator iterInner = new Iterator();
while(iter.hasNext()){
//LinkedList entry = (LinkedList)iter.next();
LinkedList myList = new LinkedList();
Map.Entry entry = (Map.Entry)iter.next();
myList = (LinkedList) (entry.getValue());
Iterator iterate = myList.iterator();
while (iterate.hasNext())
{
LinkedHashMap entry2 = (LinkedHashMap)iterate.next();
if(fileType=="mav2opc")
{
String deviceName1 = entry2.get("DeviceName").toString();
String userName = entry2.get("UserName").toString();
String password = entry2.get("Password").toString();
String deviceType = entry2.get("DeviceType").toString();
String ipAddress = entry2.get("IPAddress").toString();
myDevice = new Device(deviceName1, userName, password, deviceType,ipAddress);
openJSON(deviceType,deviceName1);
System.out.println(myDevice);
} else
{
//Add a tag
String tagName = entry2.get("tagName").toString();
String tagType = entry2.get("tagType").toString();
String tagXPath = entry2.get("tagXPath").toString();
String tagWritable = entry2.get("tagWritable").toString();
}
}
}
//System.out.println("==toJSONString()==");
//System.out.println(JSONValue.toJSONString(json));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(ParseException pe){
System.out.println(pe);
}
return myDevice;
}
}
Ok, so you have two files, one with list of devices and the other, per-device file, which has attributes of the device. The structures of the two files is exactly same, I am guessing something like
The devices file:
{{"DeviceName:"d1","UserName":"u1","Password":"p1","DeviceType":"t1","IPAddress":"i1"},
{"DeviceName:"d2","UserName":"u2","Password":"p2","DeviceType":"t2","IPAddress":"ir"}}
And the per-device file
{{"tagName:"n1","tagType":"t1","tagXPath":"X1","tagWritable":true}}
In the per-device file there is only one map, though it is inside a list. The processing logic is to open the file, create the parser, read json and for each entry in the list process the map.
The logic for processing the map is the only difference between the two. Note that right now you are discarding what you read from the per-device file, which you will have to store somewhere in the myDevice
One way to do this is using a callback: create an interface MapHandler that has a method process. openJSON takes a parameter of this type and calls process on it for each method.
The device-level handler can be constructed with the myDevice being processed and set the fields.

Convert JSON to Map

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.

Categories

Resources