Jump to content

xml vs json


ds1-e

Recommended Posts

  • Scripting Moderators

Hey. As title says, which thing is better, xml or json?

I want to save player settings in player cache.

- What is more efficient?

- What is easier to use?

If you can, i would like to see an example how to use both.

Link to comment
  • Administrators

Currently, JSON is better for something like that. You can store that information in a database (which is way more efficient than reading/writing XML files)

I would give an example, but there really isn't much to show.

  • Like 1
Link to comment
  • Moderators

I also think JSON is better and simpler.

 

local table = {
	[1] = "asd",
	[2] = "qwe",
}

local JSON = toJSON(table) -- convert table to JSON. (JSON is a string, you need to store that like a string)
print(JSON) -- you can print it

local table_again = fromJSON(JSON) -- convert JSON back to table
-- table and table_again is equal

 

Edited by stPatrick
  • Like 1
Link to comment

JSON is simpler, but it has its limits and data size. For example, I was faced with the fact that JSON returned an empty table from a very large JSON. Here for each situation individually. Personally, I would prefer to write something small in JSON. In other cases, come up with something more rational.

  • Like 1
Link to comment
  • Scripting Moderators
41 minutes ago, XaskeL said:

JSON is simpler, but it has its limits and data size. For example, I was faced with the fact that JSON returned an empty table from a very large JSON. Here for each situation individually. Personally, I would prefer to write something small in JSON. In other cases, come up with something more rational.

I will need just save a few settings for player, nothing big. I'll try it out, thank you guys for answers.

Link to comment
  • Moderators

XML has most of the cons. It is also much older, so it is to be expected.

 

There are a few XML haters on the community, so I will keep it short.

So a few pro's:

- Readability is very high, especially in case of inheritance. In JSON that can also be good, but you will need a proper reader for that.

- Maintenance. In case of breaking it, it is very easy to fix it. (That being said, it breaks easier if you do not know the rules.)

- Saving JSON inside the notes and keeping a secondary XML layer of properties that do not have to be saved in your main data. There are not many user cases where you want that on clientside. Unless you have a shared settings file for all resources. In that case you only have to parse JSON of a specific resource node.

- (not related to player settings) Can be use for multiple files that are already integrated in mta. XML, map, (acl*)

 

So JSON? Yes, if you keep your lua table it's structure: arrays and object separated.

Edited by IIYAMA
  • Like 1
  • Thanks 1
Link to comment
  • Scripting Moderators
14 hours ago, IIYAMA said:

XML has most of the cons. It is also much older, so it is to be expected.

 

There are a few XML haters on the community, so I will keep it short.

So a few pro's:

- Readability is very high, especially in case of inheritance. In JSON that can also be good, but you will need a proper reader for that.

- Maintenance. In case of breaking it, it is very easy to fix it. (That being said, it breaks easier if you do not know the rules.)

- Saving JSON inside the notes and keeping a secondary XML layer of properties that do not have to be saved in your main data. There are not many user cases where you want that on clientside. Unless you have a shared settings file for all resources. In that case you only have to parse JSON of a specific resource node.

- (not related to player settings) Can be use for multiple files that are already integrated in mta. XML, map, (acl*)

 

So JSON? Yes, if you keep your lua table it's structure: arrays and object separated.

 

Yes, i will try it out, if i wouldn't understand something, i'll give you answer in this topic.

Link to comment
  • Scripting Moderators
5 hours ago, savour said:

actually if you don't know both of them, i'd say go with XML for now. and here is an example

Hmm, but i heard that XML isn't that efficient, is that related in anyway with saving player settings in cache?

Or this doesn't change anything? I mean in server efficienty.

Link to comment
  • Moderators
51 minutes ago, majqq said:

Hmm, but i heard that XML isn't that efficient, is that related in anyway with saving player settings in cache?

Or this doesn't change anything? I mean in server efficienty.

It is less efficient because:

- Tables are a very different format than XML. That means that you have to write and convert the data with a lot more extra code.

- It isn't compact, the filesize will be a lot bigger incompare to JSON.

 

  • Like 2
  • Thanks 1
Link to comment
  • Scripting Moderators
On 30/03/2019 at 22:33, IIYAMA said:

It is less efficient because:

- Tables are a very different format than XML. That means that you have to write and convert the data with a lot more extra code.

- It isn't compact, the filesize will be a lot bigger incompare to JSON.

 

Well looks like i almost finished it in JSON, but it shows me nil, whenever i want to retrieve data. Can u help me with that?

-- onClientResourceStart

	if fileExists("settings") then
		local settingsFile = fileOpen("settings")
		if settingsFile then
			local loadSettings = fileRead(settingsFile, fileGetSize(settingsFile))
			local loadedData = fromJSON(loadSettings)
			fileClose(settingsFile)
		end
	end
end
addEventHandler("onClientResourceStart", resourceRoot, onClientResourceStart)
-- settings json file

[ { "7": false, "1": "Test item", "2": false, "4": false, "8": false, "9": false, "5": false, "10": false, "3": false, "6": false } ]
-- table structure which is saved

playerData = {playerItems = {[1] = false, [2] = false, [3] = false, [4] = false, [5] = false, [6] = false, [7] = false, [8] = false, [9] = false, [10] = false}}

 

Link to comment
  • Moderators
5 minutes ago, majqq said:

Well looks like i almost finished it in JSON, but it shows me nil, whenever i want to retrieve data. Can u help me with that?


-- onClientResourceStart

	if fileExists("settings") then
		local settingsFile = fileOpen("settings")
		if settingsFile then
			local loadSettings = fileRead(settingsFile, fileGetSize(settingsFile))
			local loadedData = fromJSON(loadSettings)
			fileClose(settingsFile)
		end
	end
end
addEventHandler("onClientResourceStart", resourceRoot, onClientResourceStart)

-- settings json file

[ { "7": false, "1": "Test item", "2": false, "4": false, "8": false, "9": false, "5": false, "10": false, "3": false, "6": false } ]

-- table structure which is saved

playerData = {playerItems = {[1] = false, [2] = false, [3] = false, [4] = false, [5] = false, [6] = false, [7] = false, [8] = false, [9] = false, [10] = false}}

 

You forgot the file format

Link to comment
  • Scripting Moderators
22 minutes ago, stPatrick said:

You forgot the file format

Well, i want this file without a format (i think it's possible, i saw settings files without format), it saves normal, load normal, but i don't know how to retrieve data after loading it.

For some reason sometimes json file without any changes looks like that, you should look at the end of line, is it intended?

-- settings json file

[ { "7": false, "1": false, "2": false, "4": false, "8": false, "9": false, "5": false, "10": false, "3": false, "6": false } ]se } ]

 

Maybe something wrong is in saving? This is the same onClientResourceStart, just first lines.

function onClientResourceStart()
	if not fileExists("settings") then
		local settingsFile = fileCreate("settings")
		if settingsFile then
			local jsonData = toJSON(playerData.playerItems)
			fileWrite(settingsFile, jsonData)
			fileClose(settingsFile)
		end
	end
  -- later loading function.

addEventHandler("onClientResourceStart", resourceRoot, onClientResourceStart)

 

Edited by majqq
Link to comment
  • Moderators
1 hour ago, majqq said:

Well looks like i almost finished it in JSON, but it shows me nil, whenever i want to retrieve data. Can u help me with that?


-- onClientResourceStart

	if fileExists("settings") then
		local settingsFile = fileOpen("settings")
		if settingsFile then
			local loadSettings = fileRead(settingsFile, fileGetSize(settingsFile))
			local loadedData = fromJSON(loadSettings)
			fileClose(settingsFile)
		end
	end
end
addEventHandler("onClientResourceStart", resourceRoot, onClientResourceStart)

-- settings json file

[ { "7": false, "1": "Test item", "2": false, "4": false, "8": false, "9": false, "5": false, "10": false, "3": false, "6": false } ]

-- table structure which is saved

playerData = {playerItems = {[1] = false, [2] = false, [3] = false, [4] = false, [5] = false, [6] = false, [7] = false, [8] = false, [9] = false, [10] = false}}

 

As I mentioned before, do not mix arrays and objects in same table in Lua. For some unknown reason that has happend here.

The json I am looking at contains an object instead of an array.

Object: { }

Array: [ ]

 

Try to not assign the items to specific indexes, but keep it untouched.

 

In your current code the items can be accessed using a string "1", "2" etc.

Use: iprint to figure out more info.

  • Like 1
  • Thanks 1
Link to comment

In which scope does it appear as nil? Right after loading it or later on somewhere else? I have a feeling this is about scope of variables: you load the data into a local variable which means it's only accessible in that same scope/block/function you're working in. Have you tried adding a debug output for 'loadedData' right after fromJSON'ing it?

  • Like 1
Link to comment
  • Scripting Moderators
4 hours ago, MrTasty said:

In which scope does it appear as nil? Right after loading it or later on somewhere else? I have a feeling this is about scope of variables: you load the data into a local variable which means it's only accessible in that same scope/block/function you're working in. Have you tried adding a debug output for 'loadedData' right after fromJSON'ing it?

It returns a table. 

 

4 hours ago, IIYAMA said:

As I mentioned before, do not mix arrays and objects in same table in Lua. For some unknown reason that has happend here.

The json I am looking at contains an object instead of an array.

Object: { }

Array: [ ]

 

Try to not assign the items to specific indexes, but keep it untouched.

 

In your current code the items can be accessed using a string "1", "2" etc.

Use: iprint to figure out more info.

I am a bit confused, sorry if i misunderstood you.

 

-- an other table
playerItems = { fastkey_1 = false, fastkey_2 = false, fastkey_3 = false, fastkey_4 = false, fastkey_5 = false, fastkey_6 = false, fastkey_7 = false, fastkey_8 = false, fastkey_9 = false, fastkey_10 = false }

 

And result..

[ { "fastkey_7": false, "fastkey_10": false, "fastkey_1": false, "fastkey_5": false, "fastkey_4": false, "fastkey_6": false, "fastkey_8": false, "fastkey_3": false, "fastkey_9": false, "fastkey_2": false } ]se } ]

 

Edited by majqq
Link to comment
  • Scripting Moderators
32 minutes ago, majqq said:

It returns a table. 

 

I am a bit confused, sorry if i misunderstood you.

 


-- an other table
playerItems = { fastkey_1 = false, fastkey_2 = false, fastkey_3 = false, fastkey_4 = false, fastkey_5 = false, fastkey_6 = false, fastkey_7 = false, fastkey_8 = false, fastkey_9 = false, fastkey_10 = false }

 

And result..


[ { "fastkey_7": false, "fastkey_10": false, "fastkey_1": false, "fastkey_5": false, "fastkey_4": false, "fastkey_6": false, "fastkey_8": false, "fastkey_3": false, "fastkey_9": false, "fastkey_2": false } ]se } ]

 

 

By the way i probably learned how to load data from JSON file, but i'm thinking if this thing which are you talking about can broke file.

Edited by majqq
Link to comment
  • Moderators

 

@majqq

Oke let me explain you the difference between Lua tables and objects / arrays in JavaScript. (JSON = JavaScript Object Notation)

 

 


 

 

Here we have a table with array structure in Lua:

local thisArray = {1, 2, 3, 4}

 

Here we have a table with object structure in Lua:

local thisObject = {a = 1, b = 2, c = 3, d = 4}

 

Here we have a table with an mixed structure in Lua:

local thisMix = {a = 1, b = 2, 3, 4}

 

As you can see those are tables. There is no such thing as arrays or objects in Lua.

 

 


 

 

But if we were to transform them to JavaScript:

Array

const thisArray = [1, 2, 3, 4];

 

Object

const thisObject = {a: 1, b: 2, c: 3, d: 4};

 

There is NO mixed in JavaScript!

If you insert a mixed Lua table in JSON (JavaScript Object Notation), the structure will be an OBJECT ?

 

 


 

 

Afaik this is what is happening to you, except it doesn't look like you are doing the same thing... :buzzsaw:

 

local thisMix = {a = 1, b = 2, 3, 4}

 

To JSON

....................

From JSON

 

local thisMix = {a = 1, b = 2,  ["1"] = 3, ["2"] = 4}
-- or
local thisMix = {["a"] = 1, ["b"] = 2,  ["1"] = 3, ["2"] = 4}

 

 

 


 

 

 

So how about try it without defining any keys. Because I really have no other idea why else it would change it to an object.

playerData = {playerItems = {false, false, false, false, false, false, false, false, false, false}}

 

 

 

 

 

 

 

 

 

 

 

Edited by IIYAMA
  • Like 1
  • Thanks 1
Link to comment
  • Scripting Moderators
1 hour ago, IIYAMA said:

 

@majqq

Oke let me explain you the difference between Lua tables and objects / arrays in JavaScript. (JSON = JavaScript Object Notation)

 

 


 

 

Here we have a table with array structure in Lua:


local thisArray = {1, 2, 3, 4}

 

Here we have a table with object structure in Lua:


local thisObject = {a = 1, b = 2, c = 3, d = 4}

 

Here we have a table with an mixed structure in Lua:


local thisMix = {a = 1, b = 2, 3, 4}

 

As you can see those are tables. There is no such thing as arrays or objects in Lua.

 

 


 

 

But if we were to transform them to JavaScript:

Array


const thisArray = [1, 2, 3, 4];

 

Object


const thisObject = {a: 1, b: 2, c: 3, d: 4};

 

There is NO mixed in JavaScript!

If you insert a mixed Lua table in JSON (JavaScript Object Notation), the structure will be an OBJECT ?

 

 


 

 

Afaik this is what is happening to you, except it doesn't look like you are doing the same thing... :buzzsaw:

 


local thisMix = {a = 1, b = 2, 3, 4}

 

To JSON

....................

From JSON

 


local thisMix = {a = 1, b = 2,  ["1"] = 3, ["2"] = 4}
-- or
local thisMix = {["a"] = 1, ["b"] = 2,  ["1"] = 3, ["2"] = 4}

 

 

 


 

 

 

So how about try it without defining any keys. Because I really have no other idea why else it would change it to an object.


playerData = {playerItems = {false, false, false, false, false, false, false, false, false, false}}

 

 

 

 

 

 

 

 

 

 

 

 

[ [ false, false, false, false, false, false, false, false, false, false ] ]se ] ]

 

And this is result. :v

Maybe i should use XML?

Edited by majqq
Link to comment
  • Scripting Moderators

Maybe something wrong is here. Cannot edit my post above.

function onClientResourceStop()
	if fileExists("settings") then
		local settingsFile = fileOpen("settings")
		if settingsFile then
			local jsonData = toJSON(playerData.playerItems)
			fileWrite(settingsFile, jsonData)
			fileClose(settingsFile)
		end
	end
end
addEventHandler("onClientResourceStop", getRootElement(), onClientResourceStop)

 

Link to comment
  • Moderators

It looks fine, except for: (not sure if it is your typo)

 

[ [ false, false, false, false, false, false, false, false, false, false ] ]se ] ]

What happens if you debug:

jsonData 

?

 

@majqq

 

P.s don't forget to clean the file before testing again.

Oh and use resourceRoot for the even handler ?

Edited by IIYAMA
  • Like 1
  • Thanks 1
Link to comment
  • Scripting Moderators
6 minutes ago, IIYAMA said:

It looks fine, except for: (not sure if it is your typo)

 

[ [ false, false, false, false, false, false, false, false, false, false ] ]se ] ]

What happens if you debug:


jsonData 

?

 

@majqq

 

function onClientResourceStop()
	if fileExists("settings") then
		local settingsFile = fileOpen("settings")
		if settingsFile then
			local jsonData = toJSON(playerData.playerItems)
			outputDebugString(tostring(jsonData))
			fileWrite(settingsFile, jsonData)
			fileClose(settingsFile)
		end
	end
end
addEventHandler("onClientResourceStop", getRootElement(), onClientResourceStop)

Can't be my typo. File looks like i sent above.

yFnC0gK.png

 

And settings file:

[ [ false, false, false, false, false, false, false, false, false, false ] ]se ] ]

 

Edited by majqq
  • Like 1
Link to comment
  • Scripting Moderators
5 minutes ago, IIYAMA said:

@majqq

That is a perfect result!

 

But this will write too much JSON:

 

Ah yes, i forget about that. But that isn't something wrong in the settings file?

I mean how it looks inside, it's different from debug string.

NO4m8NT.png

Edited by majqq
  • Like 1
Link to comment
  • Moderators
13 minutes ago, majqq said:

Ah yes, i forget about that. But that isn't something wrong in the settings file?

Might be the reason for writing incomplete data.

The file isn't flushed, so it might handy to do that as well:

https://wiki.multitheftauto.com/wiki/FileFlush

 

Oh and empty(recreate) the file each time you start writing data.

@majqq

The file is incorrect. There has been double written as you can see. (from a few moments before)

 

se ] ]

from:

false, false ] ]

 

Clean the file and try again.

Edited by IIYAMA
  • Thanks 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...