Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serialize class to local storage #71

Closed
intech-paul opened this issue Apr 16, 2020 · 18 comments
Closed

Serialize class to local storage #71

intech-paul opened this issue Apr 16, 2020 · 18 comments
Labels
Question Question about this project

Comments

@intech-paul
Copy link

I have a class I would like to store:

        public class MyData
        {
            public string name;
            public string address;
            public int age;

            public MyData()
            {
                name = "name";
                address = "address";
                age = 50;
            }
        }

        MyData mydata = new MyData();

to store it, I need to serilaize to string:
await localStorage.SetItemAsync("mydata",JsonConvert.SerializeObject(mydata));
this is fine, it works ok.
but when I read it back as a string, I get an error

        try{ 
        string text = await localStorage.GetItemAsync<string>("mydata");
        }
    catch (Exception ex)
    {
        exstring = ex.Message;
       return;
    }

The JSON value could not be converted to System.String. Path: $ | LineNumber: 0 | BytePositionInLine: 1. address name

Is their anyway I can read the item back as a string and deserialize myself ?

@intech-paul intech-paul added Question Question about this project Triage Issue needs to be triaged labels Apr 16, 2020
@chrissainty
Copy link
Member

You don't need to serialise the object, this library does that for you. The reason you're seeing the error is because your object has been serialised twice but only deserialised once.

@chrissainty chrissainty removed the Triage Issue needs to be triaged label Apr 16, 2020
@intech-paul
Copy link
Author

If I write the class directly, all it stores is {} for the item, and no exception is thrown.
await localStorage.SetItemAsync("mydatareal",mydata);

@chrissainty
Copy link
Member

Yes. Does that answer your question?

@intech-paul
Copy link
Author

So the SetItemAsync can't write a class ?

@chrissainty
Copy link
Member

I'm sorry I'm not following you. SetItemAsync serialises your class and the GetItemAsync deserialises it. You don't need to do any serialisation yourself.

@intech-paul
Copy link
Author

Here's a test:

    await localStorage.SetItemAsync("mydata_asclass",mydata);
    await localStorage.SetItemAsync("mydata_astext",JsonConvert.SerializeObject(mydata));

The result:

image

I know that I don't need to do this, but it proves that the class is intact
await localStorage.SetItemAsync("mydata_astext",JsonConvert.SerializeObject(mydata));

@chrissainty
Copy link
Member

chrissainty commented Apr 16, 2020

Thanks for clarifying this issue. I've just run your code and replicated what you're seeing. If I change the fields in your class to properties, everything works as expected.

I believe you're running Newtonsoft.Json to do your manual serialization. We use the new System.Text.Json library and unfortunately right now it doesn't support serialisation of fields (dotnet/runtime#876).

@intech-paul
Copy link
Author

Yes, I have it working now as well, also with a List<> of classes inside the class which is also what I am needing to use:

public class InputValues
{
    public int index { get; set; }
    public float fvalue{ get; set; }

    public InputValues()
    { }

    public InputValues(int index,float fvalue)
    {
        this.index = index;
        this.fvalue = fvalue;
    }
}

public class MyData
{
    public string name { get; set; }
    public string address { get; set; }
    public int age { get; set; }
    public List<InputValues> inputValues { get; set; }

    public MyData()
    {
        name = "name";
        address = "address";
        age = 50;

        inputValues = new List<InputValues>();
    }
}

image

My original test was using Newtonsoft.Json.

Thankyou for helping with this issue.

@chrissainty
Copy link
Member

Glad we got it sorted 🙂

@robertdunaway
Copy link

I'm having the same problem. I literally want the string back from local storage. I'm not sure why it can't do that since what it stored was a string.

Thoughts?

string serialized_appState;
serialized_appState = await _localStorage.GetItemAsync("appState") ?? "";

{"User":{"UserID":"9b02-431f-ac46-cf116fa90cf9","UserName":"","FullName":"Bob D","IsAuthenticated":true,"AuthenticatedDateTime":"2020-05-06T21:08:19.6653581+00:00","CompanyName":"Production","TenantName":"PROD","IsActive":true,"Initials":"BD","Phone":"","IsSystemAdmin":true,"IsSystemDeveloper":true,"IsTenantAdmin":true,"ConnectionString":"","Token":"7de34799-9b26-47bb-9353-185a7ffeda0c"},"PageLoadTime":"0.304"}

I'm not sure what about this value cannot be returned from localStorage as a string.

Bob

@intech-paul intech-paul reopened this May 7, 2020
@intech-paul
Copy link
Author

intech-paul commented May 7, 2020

From what I found the Set/Get operations find the "{" as part of the first character as an indicator that it is to be a json string so has to be deserilaized into json.
Also, your class has to be defined with all items {get; set}

You are best to try to read/write strings as a basic test.

NOTE:
there is a breaking change on VS Version 16.6.0 Preview 5.0 that stops the local storage working when you run the app from within the IDE, if you run the blazor app directly from a browser with https://localhost:44370/ it works properly. I have notified MS of this by the report a problem.

@robertdunaway
Copy link

This is great information.

At one time this worked. I'm not sure when it stopped working because the app still functions without it. Or am I imagining that?

Did it work with { at one time?

@intech-paul
Copy link
Author

I could not get it to work when the string had a { in it, but I am not sure if that was my class definition or not.
"MyTestString" is a great place to start, also you can have a look at the local storage in the chrome Test Info (CTRL+SHIFT+I)
Application, Local storage to see if the data is there or not.

image

@robertdunaway
Copy link

There has got to be a way to get a string value out of it even if it is a JSON string.

I'm trying a few things without luck. I can't even believe it's an issue. Seems like something that should just work.

@robertdunaway
Copy link

If I figure it out I'll post it here.

@robertdunaway
Copy link

This seems to work but other things are breaking. I'll check that out.

Just wanted to share that using object seems to help.

                object serialized_appState;
                //serialized_appState = await _localStorage.GetItemAsync<string>("appState");
                serialized_appState = await _localStorage.GetItemAsync<object>("appState");

@robertdunaway
Copy link

That did the trick. I can get the JSON string as object and when I'm ready to use it I can deserialize it into the class I need.

The Blazored.LocalStorage has been a great tool. Thanks.
Bob

@chrissainty
Copy link
Member

@robertdunaway Can you please open a separate issue for your problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Question Question about this project
Projects
None yet
Development

No branches or pull requests

3 participants