ex4nicegui icon indicating copy to clipboard operation
ex4nicegui copied to clipboard

How to get all the XXXProxy properties of a ViewModel-based class?

Open ShannonZ opened this issue 1 year ago • 5 comments

The class derived from rxui.ViewModel is not JSON serializable, and all existing solutions to make a normal class JSON serializable no longer work. Is there any easy way to make ViewModel derived class serializable? Or any interface available to retrieve all the XXXProxy properties?

And verse vice: Is there any easy way to deserialize an instance from json string?

What I want:

from ex4nicegui import rxui
import json

class SystemParameter(rxui.ViewModel):
    SF:float = 42.0
    RFA:float = 100.0
    PW90:float = 10.0
    Gx_offset:int = 0
    
    def serialize(self):
        with open("syspar.json",'w') as f:
            s = json.dumps(self,default=vars)
            f.writelines(s)
    
   def deserialize(self,json_str:str):
        self = deserialize(json_str)

ShannonZ avatar Dec 31 '24 07:12 ShannonZ

I know what's going on now. All declared fields can only be recognized and serialized by the to_value function if they are used elsewhere.

from ex4nicegui import rxui
import json
from pathlib import Path

class SystemParameter(rxui.ViewModel):
    D1:float = 42.0
    D2:float = 100.0
    PW90:float = 10.0
    PW18:float = 20.0
    G1:int = 0
    G2:int = 0
    G3:int = 0
    D29:float = 0.001
    D30:float = 0.006
    D:float = 0
    _json_path = Path(__file__).parent/"syspar.json"
    def save_to_json(self):
        print(rxui.ViewModel.to_value(self))
        self._json_path.write_text(json.dumps(rxui.ViewModel.to_value(self)))

if __name__=='__main__':
    syspar = SystemParameter()
    print(syspar.D30)
    syspar.save_to_json()

image

ShannonZ avatar Jan 02 '25 01:01 ShannonZ

@ShannonZ You can try

from ex4nicegui import rxui
import json


class SystemParameter(rxui.ViewModel):
    SF: float = 42.0
    RFA: float = 100.0
    PW90: float = 10.0
    Gx_offset: int = 0
    _json_file = Path(__file__).parent / "syspar.json"

    def serialize(self):
        # get all reactive data as a dict
        data = rxui.ViewModel.to_value(self)

        with open(self._json_file, "w", encoding="utf-8") as f:
            s = json.dumps(data)
            f.writelines(s)

    def deserialize(self, json_str: str):
        data = json.loads(json_str)

        for key, value in data.items():
            setattr(self, key, value)

    def view(self):
        rxui.number(label="SF", value=self.SF)
        rxui.number(label="RFA", value=self.RFA)
        rxui.number(label="PW90", value=self.PW90)
        rxui.number(label="Gx_offset", value=self.Gx_offset)

        ui.button(text="Save", on_click=self.serialize)
        ui.button(
            text="Load",
            on_click=lambda: self.deserialize(self._json_file.read_text("utf-8")),
        )


sp = SystemParameter()
sp.view()

CrystalWindSnake avatar Jan 02 '25 01:01 CrystalWindSnake

@ShannonZ You can try

from ex4nicegui import rxui
import json


class SystemParameter(rxui.ViewModel):
    SF: float = 42.0
    RFA: float = 100.0
    PW90: float = 10.0
    Gx_offset: int = 0
    _json_file = Path(__file__).parent / "syspar.json"

    def serialize(self):
        # get all reactive data as a dict
        data = rxui.ViewModel.to_value(self)

        with open(self._json_file, "w", encoding="utf-8") as f:
            s = json.dumps(data)
            f.writelines(s)

    def deserialize(self, json_str: str):
        data = json.loads(json_str)

        for key, value in data.items():
            setattr(self, key, value)

    def view(self):
        rxui.number(label="SF", value=self.SF)
        rxui.number(label="RFA", value=self.RFA)
        rxui.number(label="PW90", value=self.PW90)
        rxui.number(label="Gx_offset", value=self.Gx_offset)

        ui.button(text="Save", on_click=self.serialize)
        ui.button(
            text="Load",
            on_click=lambda: self.deserialize(self._json_file.read_text("utf-8")),
        )


sp = SystemParameter()
sp.view()

In my case, a single view model class has multiple relevant views. Not all propeties/fields were used in all situation. So there are always some unused XXXProxy properties lost after to_value(). I wanna a way to get all the XXXProxy properties.

ShannonZ avatar Jan 02 '25 01:01 ShannonZ

@ShannonZ You can try

from ex4nicegui import rxui
import json


class SystemParameter(rxui.ViewModel):
    SF: float = 42.0
    RFA: float = 100.0
    PW90: float = 10.0
    Gx_offset: int = 0
    _json_file = Path(__file__).parent / "syspar.json"

    def serialize(self):
        # get all reactive data as a dict
        data = rxui.ViewModel.to_value(self)

        with open(self._json_file, "w", encoding="utf-8") as f:
            s = json.dumps(data)
            f.writelines(s)

    def deserialize(self, json_str: str):
        data = json.loads(json_str)

        for key, value in data.items():
            setattr(self, key, value)

    def view(self):
        rxui.number(label="SF", value=self.SF)
        rxui.number(label="RFA", value=self.RFA)
        rxui.number(label="PW90", value=self.PW90)
        rxui.number(label="Gx_offset", value=self.Gx_offset)

        ui.button(text="Save", on_click=self.serialize)
        ui.button(
            text="Load",
            on_click=lambda: self.deserialize(self._json_file.read_text("utf-8")),
        )


sp = SystemParameter()
sp.view()

In my case, a single view model class has multiple relevant views. Not all propeties/fields were used in all situation. So there are always some unused XXXProxy properties lost after to_value(). I wanna a way to get all the XXXProxy properties.

You may need to use from ex4nicegui import to_value

from ex4nicegui import rxui, to_value
import json

class SystemParameter(rxui.ViewModel):
    ...

    def serialize(self):
        # you can add more items to the dictionary as needed
        data = {
            "SF": to_value(self.SF),
            "RFA": to_value(self.RFA),
        }

        with open(self._json_file, "w", encoding="utf-8") as f:
            s = json.dumps(data)
            f.writelines(s)

CrystalWindSnake avatar Jan 02 '25 04:01 CrystalWindSnake

We should find a way to serialize the entire object. However, currently, there are limited options available.

CrystalWindSnake avatar Jan 02 '25 04:01 CrystalWindSnake