Skip to content

Instantly share code, notes, and snippets.

@ultimateprogramer
Forked from fenix-hub/#description.md
Last active December 30, 2023 23:57
Show Gist options
  • Save ultimateprogramer/552a6c0b81094c5c66515b065ee11188 to your computer and use it in GitHub Desktop.
Save ultimateprogramer/552a6c0b81094c5c66515b065ee11188 to your computer and use it in GitHub Desktop.
GDScript JSON <> Class Serializer/Deserializer

You can find usages in the GDScript Unirest plugin

This is a fast serializer/deserializer written in GDScript to convert a JSON (Dictionary) to a class, using something similar to the Reflection concecpt. json_to_class can be used to convert a Dictionary to a Class. All keys in the Dictionary will be treated as variables and their types will be guessed in the best way possible. A class (defined by the class_name keyword) must extend Reference or Object or be an inner class, or else Godot will not able to see its properties. It is also possible to deserialize a JSON key to a class property with a different name using the export hint as a variable name.

example usage:

class User:
    var createdAt: String
    var name: String
    var avatar: String
    var id: int

var user: Dictionary = {
 createdAt = "1601239812",
 name = "William",
 avatar = "https://google.com/images/avatar",
 id = 0
}

func _ready() -> void:
 var u: User = json_to_class(user, User.new())
 print(u.name) # will print "William"
 
 print(class_to_json(u)) # will print '{avatar=...}'
 
static func json_string_to_class(json_string: String, _class: Object) -> Object:
var parse_result: JSONParseResult = JSON.parse(json_string)
if !parse_result.error:
return json_to_class(parse_result.result, _class)
return _class
static func json_to_class(json: Dictionary, _class: Object) -> Object:
var properties: Array = _class.get_property_list()
for key in json.keys():
for property in properties:
if property.name == key and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
_class.set(key, json_to_class(json[key], _class.get(key)))
else:
_class.set(key, json[key])
break
if key == property.hint_string and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
_class.set(property.name, json_to_class(json[key], _class.get(key)))
else:
_class.set(property.name, json[key])
break
return _class
static func class_to_json_string(_class: Object) -> String:
return JSON.print(class_to_json(_class))
static func class_to_json(_class: Object) -> Dictionary:
var dictionary: Dictionary = {}
var properties: Array = _class.get_property_list()
for property in properties:
if not property["name"].empty() and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
dictionary[property.name] = class_to_json(_class.get(property.name))
else:
dictionary[property.name] = _class.get(property.name)
if not property["hint_string"].empty() and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
dictionary[property.hint_string] = class_to_json(_class.get(property.name))
else:
dictionary[property.hint_string] = _class.get(property.name)
return dictionary
extends Object
class_name JSONUtils
## Convert a JSON string to class
static func json_string_to_class(json_string: String, _class: Object) -> Object:
var json = JSON.new()
var parse_result: Error = json.parse_string(json_string)
if parse_result == Error.OK:
return json_to_class(json.data, _class)
return _class
## Convert a JSON dictionary into a class
static func json_to_class(json: Dictionary, _class: Object) -> Object:
var properties: Array = _class.get_property_list()
for key in json.keys():
for property in properties:
if property.name == key and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
_class.set(key, json_to_class(json[key], _class.get(key)))
else:
_class.set(key, json[key])
break
if key == property.hint_string and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
_class.set(property.name, json_to_class(json[key], _class.get(key)))
else:
_class.set(property.name, json[key])
break
return _class
## Convert a class into JSON string
static func class_to_json_string(_class: Object) -> String:
return JSON.stringify(class_to_json(_class))
## Convert class to JSON dictionary
static func class_to_json(_class: Object) -> Dictionary:
var dictionary: Dictionary = {}
var properties: Array = _class.get_property_list()
for property in properties:
if not property["name"].is_empty() and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
dictionary[property.name] = class_to_json(_class.get(property.name))
else:
dictionary[property.name] = _class.get(property.name)
if not property["hint_string"].is_empty() and property.usage >= (1 << 13):
if (property["class_name"] in ["Reference", "Object"] and property["type"] == 17):
dictionary[property.hint_string] = class_to_json(_class.get(property.name))
else:
dictionary[property.hint_string] = _class.get(property.name)
return dictionary
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment