46

What would be the easiest way to load a file containing JSON into a JSONObject.

At the moment I am using json-lib.

This is what I have, but it throws an exception:

XMLSerializer xml = new XMLSerializer();
JSON json = xml.readFromFile("samples/sample7.json”);     //line 507
System.out.println(json.toString(2));

The output is:

Exception in thread "main" java.lang.NullPointerException
    at java.io.Reader.<init>(Reader.java:61)
    at java.io.InputStreamReader.<init>(InputStreamReader.java:55)
    at net.sf.json.xml.XMLSerializer.readFromStream(XMLSerializer.java:386)
    at net.sf.json.xml.XMLSerializer.readFromFile(XMLSerializer.java:370)
    at corebus.test.deprecated.TestMain.main(TestMain.java:507)
Larry
  • 11,439
  • 15
  • 61
  • 84
  • 5
    Why are you using XMLSerializer for a JSON file? – Alan Moore Sep 18 '11 at 18:25
  • That was the only place I could find it read a file, the Javadoc says: `readFromFile(String path) Creates a JSON value from a File.` – Larry Sep 18 '11 at 18:28
  • I see, I would probably just read the file as a normal text, convert to a string and then JSONObject. However, I see you already have a better looking solution than that :) – Alan Moore Sep 18 '11 at 20:17

9 Answers9

41

Thanks @Kit Ho for your answer. I used your code and found that I kept running into errors where my InputStream was always null and ClassNotFound exceptions when the JSONObject was being created. Here's my version of your code which does the trick for me:

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;

import org.json.JSONObject;
public class JSONParsing {
    public static void main(String[] args) throws Exception {
        File f = new File("file.json");
        if (f.exists()){
            InputStream is = new FileInputStream("file.json");
            String jsonTxt = IOUtils.toString(is, "UTF-8");
            System.out.println(jsonTxt);
            JSONObject json = new JSONObject(jsonTxt);       
            String a = json.getString("1000");
            System.out.println(a);   
        }
    }
}

I found this answer to be enlightening about the difference between FileInputStream and getResourceAsStream. Hope this helps someone else too.

nihilman
  • 25
  • 6
janoulle
  • 1,888
  • 27
  • 29
  • 9
    I'm not a Java dev and haven't got time right now to look into it, but you may want to look at [the rejected suggested edit to this post](http://stackoverflow.com/review/suggested-edits/9220747) that purported to fix a race condition in your code here (as I understand it, file.json might get deleted between the `f.exists()` call and reading from the file, so using a try/catch is better) and consider implementing the change. Also: your answer has been mentioned on The Daily WTF forum: https://what.thedailywtf.com/t/sigh-why-do-i-even-try-a-novlet-on-stackoverflow/51280. Congratulations? – Mark Amery Sep 17 '15 at 13:25
  • 2
    @MarkAmery Yes, this is a classic [time of check to time of use](https://en.wikipedia.org/wiki/Time_of_check_to_time_of_use) bug. Also, "throws Exception" is generally a bad thing to have in main. – Powerlord Sep 17 '15 at 13:39
  • 2
    Somehow I missed the apparent edit mini-war over my comment. Ha. Thanks for the dailywtf link... quite the dubious achievement. So I can understand just how I screwed up, it's this line that causes the code to be vulnerable to the TOCTOU bug: InputStream is = new FileInputStream("file.json") re-opens the file and it may have been changed from my initial f.exists() check? – janoulle Sep 17 '15 at 14:53
  • 4
    @janoulle yes, exactly. For that reason, rather than checking if the file exists and going ahead and using it if it does, it's considered better practice to instead `try` to use the file and handle the `FileNotFoundException` if it occurs. Of course, often - perhaps even *usually* - this just won't matter at all in practice because you know that nothing's going to snatch away the file from beneath your feet if it exists, or because you don't care if your program crashes in such an edge case. But since there's no downside to the try/catch approach we may as well show best practice here. – Mark Amery Sep 17 '15 at 21:48
  • 1
    Exactly what @MarkAmery said - it's extremely unlikely to happen, but, that one time it does happen, it can really throw you for a loop. So yeah, the best practice is generally to not even check (unless you're doing the check for some other reason) and let the exception happen when it actually fails to read, then handle the missing file case in that catch block. – sloosecannon Sep 23 '15 at 17:53
  • 1
    IOUtils.toString(String str) is depracated. You have to specify encoding too, IOUtils.toString(string, encoding) like this. So in this case, it would be IOUtils.toString(is, "UTF-8") would work. – Zohaib Amir Jul 02 '16 at 12:49
30

try this:

import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;
import org.apache.commons.io.IOUtils; 

    public class JsonParsing {

        public static void main(String[] args) throws Exception {
            InputStream is = 
                    JsonParsing.class.getResourceAsStream( "sample-json.txt");
            String jsonTxt = IOUtils.toString( is );

            JSONObject json = (JSONObject) JSONSerializer.toJSON( jsonTxt );        
            double coolness = json.getDouble( "coolness" );
            int altitude = json.getInt( "altitude" );
            JSONObject pilot = json.getJSONObject("pilot");
            String firstName = pilot.getString("firstName");
            String lastName = pilot.getString("lastName");

            System.out.println( "Coolness: " + coolness );
            System.out.println( "Altitude: " + altitude );
            System.out.println( "Pilot: " + lastName );
        }
    }

and this is your sample-json.txt , should be in json format

{
 'foo':'bar',
 'coolness':2.0,
 'altitude':39000,
 'pilot':
     {
         'firstName':'Buzz',
         'lastName':'Aldrin'
     },
 'mission':'apollo 11'
}
Csa77
  • 649
  • 13
  • 19
TheOneTeam
  • 25,806
  • 45
  • 116
  • 158
  • 1
    What packages are: IOUtils, and JsonParsing from? – Larry Sep 18 '11 at 18:44
  • import net.sf.json.JSONObject; import net.sf.json.JSONSerializer; import org.apache.commons.io.IOUtils; by the way, you can use simple-json.jar as well, using the same kind of thing, you can search for that in internet. http://code.google.com/p/json-simple/ – TheOneTeam Sep 18 '11 at 18:48
  • 1
    ok thanks, but I am still not being able to resolve ‘JsonParsing’, any ideas? – Larry Sep 18 '11 at 18:54
  • would simple-json allow xml<->json conversion... does it have any dependencies (as I found with json-lib, turned out I needed to d/l 4 more jars, I want to try to keep number of dependencies down), what simple library would be good? All I need is, loading json from file, converting xml to json, pretty printing, that’s it! – Larry Sep 18 '11 at 18:57
  • 1
    @Larry JsonParsing is what ever your actual class name is. In this example public class JsonParsing = JsonParsing.class.getRe... – Dan Ciborowski - MSFT Jul 15 '14 at 02:01
  • 1
    Hey Larry, JsonParsing is class name, You can use your classname in your code. – Aditya Jun 19 '17 at 07:01
  • 1
    Looks like `JSONSerializer` has no method `toJSON` – Ghilteras Jun 11 '19 at 00:33
  • when you copy paste this code into intellij without having the apache maven dependency, it may infer another IOUtils from Sun which has a toString method which is non-Static. The solutions is to add the maven dependency and change the import. Awesome – Matt Aug 20 '21 at 17:28
27

With java 8 you can try this:

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class JSONUtil {

    public static JSONObject parseJSONFile(String filename) throws JSONException, IOException {
        String content = new String(Files.readAllBytes(Paths.get(filename)));
        return new JSONObject(content);
    }

    public static void main(String[] args) throws IOException, JSONException {
        String filename = "path/to/file/abc.json";
        JSONObject jsonObject = parseJSONFile(filename);

        //do anything you want with jsonObject
    }
}
IKo
  • 4,998
  • 8
  • 34
  • 54
  • You'd still have to include org.json code into your project. Please see https://github.com/stleary/JSON-java – MattWeiler May 03 '17 at 19:56
  • Better yet, someone put together a JAR with the org.json code: https://mvnrepository.com/artifact/org.json/json – MattWeiler May 03 '17 at 19:58
3

Another way of doing the same could be using the Gson Class

String filename = "path/to/file/abc.json";
Gson gson = new Gson();
JsonReader reader = new JsonReader(new FileReader(filename));
SampleClass data = gson.fromJson(reader, SampleClass.class);

This will give an object obtained after parsing the json string to work with.

Antariksh
  • 508
  • 8
  • 17
3

On Google'e Gson library, for having a JsonObject, or more abstract a JsonElement:

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

JsonElement json = JsonParser.parseReader( new InputStreamReader(new FileInputStream("/someDir/someFile.json"), "UTF-8") );

This is not demanding a given Object structure for receiving/reading the json string.

Edit 2021-May-13: As I commented myself: This solution does not properly take care of closing streams!
This does:

JsonElement json = null;
try (Reader reader = new InputStreamReader(new FileInputStream("/someDir/someFile.json"), "UTF-8")) {
    json = JsonParser.parseReader( reader );
} catch (Exception e) {
    // do something
}

As one can see the code gets bloated when doing correctly. I would clean-code move the 'loading of a json from a file' into a FileUtils.class; which probably already exists and does super nice adjustable Exception handling...

Dirk Schumacher
  • 1,479
  • 19
  • 37
  • About 7 months later I see the somewhat downside: Streams are not being closed. Nevertheless theoretically I wish default behaviour would close the stream by the underlaying consuming instance. since this instance knows when it is done and most of the times there the stream will not be used anymore... on the other hand it is not the consumers responsibility since I also follow the idea: 'who opens needs to close' it is a dilemma :-( – Dirk Schumacher Feb 06 '21 at 21:32
0

Example of json which I am using:

"identity" : {
  "presentProvince" : [ {
    "language" : "eng",
    "value" : "China"
  } ],
  "presentAddressLine1" : [ {
    "language" : "eng",
    "value" : "bjbjbhjbhj"
  } ],
 "permanentAddressLine4" : [ {
    "language" : "eng",
    "value" : "123456"
  } ]
} } 

Here is the code to access language and value:

public static void JsonObjParsing() throws Exception {
    File f = new File("id.json");
    if (f.exists()){
        InputStream is = new FileInputStream(f);
        String jsonTxt = IOUtils.toString(is, "UTF-8");
        System.out.println(jsonTxt);
            
            
        JSONObject json = new JSONObject(jsonTxt); 
           
        JSONObject identity = json.getJSONObject("identity");
            
            
        JSONArray identityitems = identity.getJSONArray("presentProvince");
        for (Object o : identityitems) {
            JSONObject jsonLineItem = (JSONObject) o;
            String language = jsonLineItem.getString("language");
            String value = jsonLineItem.getString("value");
            System.out.println(language +" " + value);
        }
    } 
}


public static void main(String[] args) throws Exception {
    JsonObjParsing();
}
svarog
  • 9,477
  • 4
  • 61
  • 77
Nee
  • 11
  • 3
0

A way of getting both array of json in file or simply json would be

InputStream inputStream= Employee.class.getResourceAsStream("/file.json");
CollectionType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, Employee.class);

List<Employee> lstEmployees = mapper.readValue(inputStream, collectionType);

The file.json needs to be placed in the resources folder. If your file only has a json block without json array square brackets [] , you can skip the CollectionType

InputStream inputStream= Employee.class.getResourceAsStream("/file.json");
Employee employee = mapper.readValue(inputStream, Employee.class);

Also refer here for original answer from where I have drawn.

veritas
  • 378
  • 1
  • 6
  • 16
0
import org.springframework.transaction.annotation.Transactional;
import org.springframework.core.io.ByteArrayResource;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.File;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.minidev.json.JSONObject;
    
    String filename = "xyz.json";
    
    @Transactional
        public Object getFileInternalJsonData(String filename) {
            try {
                ByteArrayResource inputStream = new ByteArrayResource(Files.readAllBytes(Paths.get("D:\MyData\test\" + File.separator + filename)));
                return new ObjectMapper().readValue(inputStream.getInputStream(), Object.class);
            } catch (Exception e) {
                return new JSONObject().appendField("error", e.getMessage());
            }
        }
  • 2
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 08 '22 at 08:54
0

You can try the below code, the main advantage for this code is you don't need to use any external dependency like org.json.simple

String resourceName = "response.json";
        //InputStream is = JSONMapperImpl.class.getResourceAsStream(resourceName);
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        InputStream resourceStream = loader.getResourceAsStream(resourceName);
        if (resourceStream == null) {
            throw new NullPointerException("Cannot find resource file " + resourceName);
        }

        JSONTokener tokenizer = new JSONTokener(resourceStream);
        JSONObject object = new JSONObject(tokenizer);

If you are facing any dependency issue then please add below dependency in your pom.xml file

    <dependency>
        <groupId>org.json</groupId>
        <artifactId>json</artifactId>
        <version>20220924</version>
    </dependency>
Muhammed Fasil
  • 7,909
  • 2
  • 19
  • 28