Serializing and deserializing a ArrayList

Hello!

I am trying to serialize and deserialize a arraylist of objects. This object is called Pager and is defined as follows:

    public class Pager
    {
        public int ID { get; set; }
        public int RIC { get; set; }
        public string Name { get; set; }
        public string SerialNumber { get; set; }
    }

In a different class, I have made an Arraylist containing these Pagers.
I want to be able to save this list of pagers to my SD card as a JSON file and then read it back again.

I have been able to serialize the arraylist correctly by doing this:

var result = JsonConverter.Serialize(Pagers.ToArray()).ToString();

Now, however when I try to deserialize by running below code:

var bson = JsonConverter.Deserialize(result).ToBson();

Pager[] pagers = (Pager[]) JsonConverter.FromBson(bson, typeof(Pager[]));

I get this error:

#### Exception System.NullReferenceException - CLR_E_NULL_REFERENCE (1) ####
#### Message: 
#### GHIElectronics.TinyCLR.Data.Json.JsonConverter::PopulateObject [IP: 0013] ####
#### GHIElectronics.TinyCLR.Data.Json.JsonConverter::PopulateObject [IP: 036d] ####
#### GHIElectronics.TinyCLR.Data.Json.JsonConverter::FromBson [IP: 000d] ####
#### PagerServerV3._0.Files.PagerFile::AddPager [IP: 0032] ####
#### PagerServerV3._0.Program::Main [IP: 006a] ####
 Exception thrown: 'System.NullReferenceException' in GHIElectronics.TinyCLR.Data.Json.dll
An unhandled exception of type 'System.NullReferenceException' occurred in 
 GHIElectronics.TinyCLR.Data.Json.dll

I don’t know of a different way of deserializing my data. What am I doing wrong?

Also, is it possible to use something else than an arraylist? E.g. a normal C# list for example.

I would really appreciate if someone could help me out here.

https://docs.ghielectronics.com/software/tinyclr/tutorials/serialization.html

Thank you for your reply, but if you look at the code in the tutorial you sent and at mine, you see that they are practically the same.

I followed that tutorial, it’s what got me here in the first place.

Convert byte[] to string with Encoding.UTF8.GetBytes() and use DeserializeObject()

ToBson() FromBson() didnt work for me either.

public static byte[] Serialize(object data)
            {
                JToken json = JsonConverter.Serialize(data);
                string jsonString = json.ToString();
                byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
                return jsonBytes;
            }

    public static Pager Deserialize(byte[] data)
            {
                if (data.Length > 0)
                {
                    string byteString = Encoding.UTF8.GetString(data);
                    Pager pager = (Pager)JsonConverter.DeserializeObject(byteString, typeof(Pager));
                    return pager;
                }
                return null;
            }
1 Like

Thank you! With this code I was able to solve my problem.

What changed in 2.1 preview 4 this does not work anymore?

 #### Exception System.NullReferenceException - CLR_E_NULL_REFERENCE (4) ####
    #### Message: 
    #### System.AppDomain::CreateInstanceAndUnwrap [IP: 0013] ####
    #### GHIElectronics.TinyCLR.Data.Json.JsonConverter::DefaultInstanceFactory [IP: 008a] ####
    #### GHIElectronics.TinyCLR.Data.Json.JsonConverter::PopulateObject [IP: 0027] ####
    #### GHIElectronics.TinyCLR.Data.Json.JsonConverter::DeserializeObject [IP: 000c] ####

edit: 6 days ago, there is a mention that enums dont work
Json Deserialized example - TinyCLR OS - GHI Electronics’ Forums
but they worked in TinyCLR 2.0

edit2: tried without enum, only simple int, same error

@mcalsyn helped with some fixes. Any ideas Martin?

I’m not sure if my answer exactly matches your problem, but just yesterday I ported @mcalsyn ‘JSON round-trip’ example to TinyCLR v2.1.0 Preview 4. There was a change needed regarding ‘CreateInstance’
I was not successful with enum but didn’t try for a longer time.
-GitHub - RoSchmi/JSON_for_TinyCLR: JSON round-trip examples for TinyCLR v2)

Looking at your Pager type and the code, that’s pretty straightforward and would seem to be covered by the existing unit tests. Is that still representative of you code that is failing? I will try to construct a program with those snippets to see if I can repro the problem.

There was a change to support polymorphic types and it’s always possible that I broke something, but my unit tests (which include basic types, complex types, arrays, and polymorphic classes) did pass. If you have an instance factory, the signature changed.

This crash isn’t ringing any bells with me, but I will run some tests and see if I can reproduce the problem using your fn’s and Pager type.

I added the code from this thread and just ran the unit test program, with these new routines and a call to DoLucaPTest(), and got no failures. Can you provide a minimal example of the failing code? Was there some other data structure (like an ArrayList) involved?

EDIT: I see now that Darko is posting the problem. I (not unreasonably) assumed that the ‘this’ that Darko was referring to was the example code in this thread, though maybe some other code is involved. If there was some other code pattern involved, then I will need an example of the failure so that I can repro.

public class Pager
{
    public int ID { get; set; }
    public int RIC { get; set; }
    public string Name { get; set; }
    public string SerialNumber { get; set; }
}

    public static byte[] LucaP_Serialize(object data)
    {
        JToken json = JsonConverter.Serialize(data);
        string jsonString = json.ToString();
        byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
        return jsonBytes;
    }

    public static Pager LucaP_Deserialize(byte[] data)
    {
        if (data.Length > 0)
        {
            string byteString = Encoding.UTF8.GetString(data);
            Pager pager = (Pager)JsonConverter.DeserializeObject(byteString, typeof(Pager));
            return pager;
        }
        return null;
    }

    private static void DoLucaPTest()
    {
        var pager = new Pager
        {
            ID = 1,
            RIC = 2,
            Name = "foo",
            SerialNumber = "123",
        };

        var data = LucaP_Serialize(pager);
        var result = LucaP_Deserialize(data);

        if (result.ID != pager.ID ||
            result.RIC != pager.RIC ||
            result.Name != pager.Name ||
            result.SerialNumber != pager.SerialNumber)
        {
            throw new Exception("LucaP test failed");
        }
    }

Are you using an on-chip unit test or are you jury-rigging some functionality in visual studio to test this? how are you going about using unit tests? this is the only reasonably recent response I can find on the forums that suggests this is possible…I need to step up my game with testing because too many small bugs are getting through the cracks and I like traditional .NET unit tests a lot.

I imagine it depends on what exactly your trying to test.
I would think this Json library would port very well to test in a solution with a regular .NET nunit or xunit project and create tests against it.

For my use, I simply create 2 exact copies of the code and keep them in sync.
I run the unit tests in .NET, make any modifications and copy and paste the code back to the TinyCLR project. This works for my testing of a Memory manager for instance, but I imagine trying to test device specific functionality would require too much mocking to make it useful.

Has anyone tried this? It seems interesting.

Sadly only works on VS2017.

I always test on-chip. This code is one example why. The whole requirement for an instance factory arises out of a bug in the interpreter’s typesystem code.

I remember seeing something about that unit test system, but I haven’t played with it. It’s open source, so it could be ported to 2019.

In case your interested I have published a simple on chip test framework for TinyCLR that has a fairly complete set of Asserts based on the NUnit api style.

https://github.com/bytewizer/runtime/tree/develop/src/Bytewizer.TinyCLR.Assertions

1 Like

This is cool. I’m gonna give this a go tomorrow!

Now to learn to properly use unit tests…

You will find lots of examples under the playground folder you can check out.

1 Like