Jun 24, 2013

Reading and parsing a JSON file with LibGDX

There are many reasons why you would need to read a JSON file in your libgdx (android or desktop) application. For example, you could store the configuration of your app, or maybe data stored about some game configuration you need.

If you need to read a JSON file, you can go and read the official LibGDX guide. I've done so and after a lot of trial and error I made it work. I also include here the code needed to read a plain text JSON file using LibGDX, which is also very useful for many other tasks.

First, you must know what kind of data you want to read, and therefore you must create the JSON file accordingly. I have taken the official LibGDX documentation about JSON parsing, and twisted the example to fit my needs. Here is my JSON file:

{
enemies: [
        {
                type: "billy",
                x: 10,
                y: 15
        },
        {
                type: "sammy",
                x: 11,
                y: 13
        }
],
name: Lab
}
The example is supposed to be the configuration of a certain map. You can see that I have a list of enemies first, with three fields: type, x, and y (position of the enemy on the map). Finally I have the name of the map where the enemies are located.

You need to create two classes: one for the enemies data (with the three members: type, x and y, it's better to use the same name you used on your JSON but you can change that too). And the root class. In my example I called them Config (for the root) and Position (for the enemy positions):

    public static class Config{
         private ArrayList enemies;
         private String name;
    }
   

    public static class Position {
        private String type;
        private int x;
        private int y;
    }
Please note that these two classes are static! Otherwise the compiler will throw an error. Note also that I made this two classes internal for my Map class, and therefore it seems Java wants them to be static also.
Also note that we use ArrayList in order to store several elements, though we don't tell their type.

 Finally, here is the code to load and deserialize the JSON file you created some steps before (called "map.json" in my example). Please note also that there are many ways to set the FileHandle object, in my case I made the file internal and located it into the "assets" folder, since it's meant to be an android project someday:
    public void loadJson(){       
        FileHandle handle = Gdx.files.internal("assets/map.json");
        String fileContent = handle.readString();                  
        Json  json = new Json();
        json.setElementType(Config.class, "enemies", Position.class);
        Config data = new Config();
        data = json.fromJson(Config.class, fileContent);
        Gdx.app.log(GameManager.LOG, "Data name = " + data.name);
        for(Object e :data.enemies){  
            Position p = (Position)e;
            Gdx.app.log(GameManager.LOG, "type = " + p.type + "x = " + p.x + "y =" + p.y);
        }
    }   

The explanation is simple. Firstly, we create a FileHandle with the file name and the correct location of the JSON file. After that, we read it's contents and put them into a String object. After that, we create a JSON object and we tell it that there is some element into Config class that it's of Position class, and it's marked by the tag "enemies". Then we create a Config object, which will hold the deserialized data. With the call to "json.fromJson" we deserialize the fileContent string and turn it into a Config object.
After that, we can print happily the contents of our object, in this case the Object returned by the ArrayList must be casted to Position in order to get the correct data to print.
    
I hope this helps the LibGDX community in some way, since the documentation is a bit scarce and examples of usage are not that easy to find on the net. Just let me know in the comments if you know how to improve this code, your impressions or problems with this stuff.

8 comments:

  1. Do you checked you JSONValue class? Also trying to find a way how to use json with libgdx.

    ReplyDelete
    Replies
    1. Hi Bojan, I still didn't mess with JsonValue class. But you can find more info here: http://code.google.com/p/libgdx/wiki/JsonParsing. For what I read, this class represents the data inside the JSon file so you can use it afterwards, but for my purposes (only reading some little data), the code above is fine.

      Delete
  2. I have an error "Couldn't find type of class "java.lang.Enum""?
    Does anybody have the same problem?

    ReplyDelete
    Replies
    1. Did you try to include it on your file? I don't have such an error, sorry. Maybe it's not related to libgdx?

      Delete
  3. thx for this tutorial... helped a lot!!!!

    ReplyDelete
    Replies
    1. Thanks for coming and reading my blog, happy to help :-)

      Delete
  4. Thanks Dr V, as you say not many examples out there. Yours has helped me scale up my game. Much appreciated.

    ReplyDelete
    Replies
    1. Glad to help you :-) Good luck with the game!

      Delete