Hello There, Guest! Login or Register


Tutorial: Loading static information using JSON
#1
Tutorial: Loading static information using JSON
Ask yourself: if you want to add a new cash point to the gamemode, is that a good reason to have to re-compile the whole thing? No. Then ask yourself a second question: should it be possible to change the cash point file during gamemode execution? No. One final question: how easy should it be to add a new cash point? Dead easy.

And that is where JSON comes into play. By separating data which should rarely change, such as cash points and ammunation locations, away from the gamemode, maintaining it will become a lot easier for non-developers as well. JSON is a good file format here, because it's human readable and has a very clear structure. Data stored in JSON files should be considered static, and will therefore not be changeable in the gamemode: you don't add a new ammunation location every day. For that reason, it can be completely read only.

The basic structure of a JSON document
JSON is a very simple file format. As can be seen on the official website, the syntax is very simple and implementations exists in tens of languages. Let's start off with the two basic formats to store data in:

[Image: json-types.jpg]

There are a few observations you can make here:
  • An object stores one or more key - value pairs. This means that every value is associated with a key unique in the object. This is the most readable way of presenting data.
  • An array stores an arbitrary number of values. The first value has index 0, the second has index 1, just like arrays in Pawn. This is most useful for smaller sets of information (<5 items) which, most of the time, share the same type and purpose.
  • The last item in either an array or an object must not be followed by a comma. This is a parsing error.

Okay. That's easy. Going forth: what exactly can a value be? The answer is simple: anything. Any key in an object can have another object as its value, arrays can hold several arrays, but of course it's also fine for them to hold strings, integers, floats or booleans. Let's look at presentations of some of the data types:

[Image: json-ponies.jpg]

That's well readable, isn't it? The LVP Pawn Editor will even allow you to collapse objects in case the files grow larger.

Las Venturas Playground's style guide for writing JSON files
In order to make sure that the files don't become a total mess, we enforce a style guide. Please take these rules into account. The image above is a good representation of what your file should look like.
  • The first line of the file should contain a comment briefly describing the purpose of the file.
  • The second line of the file should start a new object, the base of the data.
  • Each new level, either an object or an array, should be indented with four spaces.
  • A space should follow the colon character in objects, which separates keys from values.
  • If you need floats, always append ".0" after your number in case the number doesn't have decimals.

Reading JSON data in the gamemode using the JSON class
The JSON class in Las Venturas Playground's source provides all necessary functionality for reading from a JSON file. Examples of existing implementations can be found in the CashPointController and AmmunationManager classes.

The first thing you should do, is open a JSON file by calling the parse method. This will return a Node to the main object of the file, or an invalid Node in case the file couldn't be opened or the JSON was invalid. Generally, the first check you'll do is see whether the Node parse() returns is an object.

[Image: json-check.jpg]

After this piece of code, we know (1) that ponyCollectionRootNode is a valid Node, and (2) that it is an object.

We're now at the object itself. The next step is to get the name and price of the pony collection itself, which we can do using the JSON::find() method. This will search the child nodes of the object to find one where the key has the given name. Of course, we can't be sure that it exists, so critical functionality will have to determine whether it actually exists.

[Image: json-read.jpg]

Now we know the name and price of the collection. Now we need to get the individual ponies belonging to the collection. We'll do this by getting the array of objects in available with the key ponies. Since we don't know the exact number, we'll have to iterate through them, which we can do using the JSON::next() method. This will either return the next item in the array, or an invalid node in case we're already at the end.

[Image: json-readarray.jpg]

Of course, reading the "scores" entry (which now is a child of currentPony!) can be easier, because each item in the array is just a float. You must use the specific read*() method for a certain data type, as using -for example- readInteger() on a string value will return 0, regardless of its content. Finally, when you're done with reading data, you must close the JSON parser itself.

[Image: json-close.jpg]

And then you're done!

What you should keep in mind when reading JSON
JSON reading can be tricky, because you never know what you're going to get. Therefore, here are a few hints:
  • You're dealing with user data. Data can be missing, it can be invalid. If something is critical, be sure to check for it's type.
  • You must close the JSON object after you're done, by calling JSON->close().
  • Only one JSON file can be open at any given time. Opening a new file will close the old one, and invalidate all nodes.

Thank you for reading, and good luck coding!
Reply