10

Can I serialize a struct type directly since its a value type.

I have used it inside class but wondering if its possible for a struct alone.

e.g.

struct student
{
   name string; --string is a reference type
   age int;
   designation string; --string is a reference type
   salary double;
};

class foo
{
 foo(){
   student s;
   s.name = "example";

   serialize(s);
  }
}

This link says "I tried having my struct implement ISerializable, but I can't implement the required constructor because this is a struct and not an object."

Shantanu Gupta
  • 20,688
  • 54
  • 182
  • 286
  • it is possible, just follo the instruction on this link: http://stackoverflow.com/questions/628843/byte-for-byte-serialization-of-a-struct-in-c-sharp – Zalomon May 22 '15 at 15:50
  • @Zalomon: There is no accepted answer on this link even. Looking at the link, it seems developer has to write its own code somehow. But not possible directly – Shantanu Gupta May 22 '15 at 15:54
  • 1
    Just because an answer is not accepted doesnt mean it doesnt work; it may just mean the OP couldnt be bothered to click the check. It has 7 upvotes, so there is *some* value to it. Try it. – Ňɏssa Pøngjǣrdenlarp May 22 '15 at 16:02
  • 2
    @ShantanuGupta So not only do you refuse to even *try* to solve the problem yourself, you refuse to even *consider* the answer that you've been given? I guess you just have no interest in actually solving the problem. – Servy May 22 '15 at 16:07
  • My purpose is not to achieve serialization only. But to understand why how its serializing being a value type. Moreover I don't see given method is portable across different languages. If I am saving serialized object in db and trying to deserialize from another language. There is no contract defined. Also, in given solution developer has hardcoded position of each byte from where it will start. – Shantanu Gupta May 22 '15 at 16:09
  • So why does any of that mean that require that you refuse to even try to solve the problem yourself to see what happens, or what problems you have, and why does it require you to refuse to even look at any other answers that are posted to see if they work for you? If you've attempted to do this, run into problems, done research on how to solve those problems, not had them resolve your problem, and explained all of that in your question, then you'd actually have a real question. – Servy May 22 '15 at 16:12
  • You may like to read my previous comment which clearly states why I think OP might not have accepted answer as well. I see highest vote answer to be possible work around. If you have any link that explains why that's the only way to serialize a struct by hard coding position of each property. I will be more than happy to understand it. – Shantanu Gupta May 22 '15 at 16:15

2 Answers2

12

Yes, you can. I just did so with the following code.

[Serializable]
public struct TestStruct
{
    public int Value1 { get; set; }
    public int Value2 { get; set; }
    public string Value3 { get; set; }
    public double Value4 { get; set; }
}

TestStruct s1 = new TestStruct();
s1.Value1 = 43265;
s1.Value2 = 2346;
s1.Value3 = "SE";

string serialized = jss.Serialize(s1);
s2 = jss.Deserialize<TestStruct>(serialized);
Console.WriteLine(serialized);
Console.WriteLine(s2.Value1 + " " + s2.Value2 + " " + s2.Value3 + " " + s2.Value4);

What did it do? Exactly what it should have, serialized and deserialized the struct.

Output:

{"Value1":43265,"Value2":2346,"Value3":"SE","Value4":5235.3}
43265 2346 SE 5235.3

Funny, that's the TestStruct serialized and deserialized to/from JSON.

What about a default constructor? All struct objects have a default constructor, it's one of the fundamental properties of a struct object, and that default constructor is merely responsible for clearing the memory required for a struct object to the default values. Therefore, the serializer already knows there is a default constructor, and therefore can proceed as if it's a regular object (which it is).

Notes:

This example uses System.Web.Script.Serialization.JavaScriptSerializer.

This example assumes all the variables inside the struct are properties. If they are not, then this answer may not work. It seems to work for me with fields in place of the properties, but that's not a best-practice. You should always make sure that the public variables in all objects are properties.

Der Kommissar
  • 5,848
  • 1
  • 29
  • 43
  • I am wondering how come serialization is possible for value type as we cannot create an object i.e. reference of struct. Curious to know why it won't work without property. – Shantanu Gupta May 22 '15 at 16:34
  • 1
    Because `serialization` doesn't care. If `serialization` would not let us `serialize` value types, then we could not serialize *anything*, as at some point **all** objects rely on a value type. **ALL** `struct` objects have a `default constructor`, which **all** serializers (I have come across, at least) require. You **cannot** take that away. It's one of the *fundamental properties* of a `struct` object. They should be valid *even* if all the memory they contain is *zeroed out*. – Der Kommissar May 22 '15 at 16:35
  • @ShantanuGupta I just ran it with those `properties` acting as `fields` and it ran successfully. The main requirements for `serialization` are that the variables be `public`, have an accessor/`getter`, and have a mutator/`setter`. – Der Kommissar May 22 '15 at 16:41
  • CS0103: The name `Serializable` does not exist in the current context. – Aaron Franke Aug 28 '17 at 02:20
  • Meant is XML serializing and that don't work! – Martin.Martinsson Apr 21 '23 at 16:54
-1

Ok, I'll make it easier for your, this is how I did it

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class IClockFingerprintTemplate
{
    public ushort Size;
    public ushort PIN;
    public byte FingerID;
    public byte Valid;
    [MarshalAs(UnmanagedType.ByValArray)]
    public byte[] Template;
}

    protected static byte[] RawSerialize(object item, Type anyType)
    {
        int structSize;
        byte[] bff;
        IntPtr ptr;

        structSize = ((IClockFingerprintTemplate)item).Size; 
        ptr = Marshal.AllocHGlobal(structSize);
        Marshal.StructureToPtr(item, ptr, true);
        bff = new byte[structSize];
        Marshal.Copy(ptr, bff, 0, 6);
        Array.Copy(((IClockFingerprintTemplate)item).Template, 0, bff, 6, structSize - 6);
        Marshal.FreeHGlobal(ptr);
    }
Zalomon
  • 553
  • 4
  • 14
  • You are using a class. I am thinking about value types i.e. struct specifically. – Shantanu Gupta May 22 '15 at 16:02
  • For strings you're gonna need a little more, such as `code`[MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public byte[] Password = new byte[5]; – Zalomon May 22 '15 at 16:04
  • This means there is always a chance of loosing characters during serialization if length of string goes beyond input specified length in struct – Shantanu Gupta May 22 '15 at 16:05
  • Why are you doing it like this? `.NET` provides `XML`, `Binary` and `JSON` serializers built in. – Der Kommissar May 22 '15 at 16:43