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.
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.
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.