Skip to content

Instantly share code, notes, and snippets.

@fenix-hub
Last active November 13, 2024 03:14
Show Gist options
  • Save fenix-hub/afeed0151f278e2b7c349be11f722765 to your computer and use it in GitHub Desktop.
Save fenix-hub/afeed0151f278e2b7c349be11f722765 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
@saatsazov
Copy link

Super nice. I'll just use your library. Thank you! I'm working on a openapi-generator adoption for a gdscript. I decided to write my own from scratch. And your library will help me to take the heavy lifting,

@fenix-hub
Copy link
Author

@saatsazov you are very welcome.
Feel free to improve this if you need.
I would love to see your project in action with this :)
Good job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment