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

Custom serialization of an arbitary type #215

Closed
jfontsaballs opened this issue Apr 8, 2019 · 18 comments
Closed

Custom serialization of an arbitary type #215

jfontsaballs opened this issue Apr 8, 2019 · 18 comments

Comments

@jfontsaballs
Copy link

Hello,

As you recommended in #214 I request a new feature which allows costumizing serialization for certain types. Maybe it could be implemented using a function that allows two delegates to be registered (or an interface with two methods). First delegate/method would provide serialization for the type; second delegate would provide deserialization. JSON.NET provides a similar functionality (see JSON.NET Implementing Custom Serialization).

Maybe you could create these delegates:

public delegate string SerializeToJson<Type>(Type instance);
public delegate Type DeserializeFrojmJson<Type>(string jsonString);

Or an equivalent interface

public interface ICustomSerializer<Type>
{
    string SerializeToJson(Type instance);
    Type DeserializeFrojmJson(string jsonString);
}

And then you could add this method to the NetJSON class:

    public static void registerCursomSerialization<Type>(SerializeToJson<Type> serializationDelegate, DeserializeFrojmJson<Type> deserializationDelegate) { ... }

// or

    public static void registerSerializer<Type>(ICustomSerializer<Type> customSerializer) { ... }

When a custom serialization is registered for a type, it is used every time this type is encountered instead of standard serialization.

Thank-you

@rpgmaker
Copy link
Owner

rpgmaker commented Apr 8, 2019

Thanks for giving all the details.

@rpgmaker
Copy link
Owner

I will take a look at this in the weekend. Thanks

@rpgmaker
Copy link
Owner

Is it fine if i don't support/ignore registration after the type has been processed by the standard serialization? The reason for this is because it faster if the custom registration is compiled into memory before the type is ever encountered instead of having to do dynamic lookup at runtime.

@jfontsaballs
Copy link
Author

My intended use case is to register custom serializations before performing any serialization, so it would be ok. Thank you very much for your great work.

@rpgmaker
Copy link
Owner

Cool. Btw for the deserialization it is a little bit complicated since it is going to be difficult to infer how much of your data needs to be read before been passed on to your custom deserializer logic as string. Currently the internal logic uses the following structure

T Deserialize(char* ptr, ref int index, NetJSONSettings settings). Would you be fine with this type of signature as it will require that you manually control the index increment to retrieve your data from the pointer provided.

I can provide a simple example of how to work with it. The only downside is over incrementing the index provided for navigation of the pointer which could cause other issue such as incomplete deserialization.

Let me know your feedback.

Thanks,

@jfontsaballs
Copy link
Author

Most of the .NET code I write is for LOB applications and we try to keep this code as free as possible from implementation details such as pointers. So, I'm no willing to use such a signature directly in my application code.

However, if you could provide an example of how to use it, I'm pretty sure I can develop some easier to use methods on top of it, which would be acceptable inside application code. To sum up, the signature you propose is adequate but some work will be necessary on my part to adapt it to my requirements ( I will try to share my code in case could be interesting for you).

Thank you very much!

@rpgmaker
Copy link
Owner

rpgmaker commented Apr 28, 2019

Here is an example of what it will look like. In my example, i created a custom class that serializes the name property as "{Name}". Let me know your thoughts, writing a custom wrapper to hide the pointers will be tough to do again unless maybe i have a stringreader class that is exposes that manages the pointer and navigation of the index internally.

So that it will end up looking more like this: T Deserialize(StringReaderEx reader, NetJSONSettings settings); instead of the below image

image

@jfontsaballs
Copy link
Author

Thanks for the example.

In my opinion, a signature using StringReader would provide protection against misuse of the pointer, which can happen (among other reasons) when trying to deserialize improperly formatted data.

If sticking with the char* signature, some means should be provided to avoid memory overrun that do not rely in proper format of the string to be deserialized (maximum value of the index parameter, for instance).

@rpgmaker
Copy link
Owner

Ok, let me try to see what I can do to abstract the pointer access. Thanks

@rpgmaker
Copy link
Owner

rpgmaker commented May 5, 2019

Still trying to figure out a way to simplify the access without exposing pointers. Thanks for been patient

@jfontsaballs
Copy link
Author

If preventing the exposure of the pointer proves to be too much work, adding an additional parameter to that signature which provides an upper limit to the index should be enough to allow the inclusion of a check, in the algorithms that implement it, to prevent a memory overrun should something unexpected occur.

With this information, an adequate abstraction can be developed on top of it at a later date if it becomes necessary.

@rpgmaker
Copy link
Owner

rpgmaker commented May 5, 2019

That is a good point. But the upper limit will be difficult to set for the caller since you cannot predict it unless your custom serialization has a fixed length for data. Upper limit will definitely allow to extract a string from the incoming json without the extra loops.

I will think about it and it see what can be done. And thanks again for the idea.

@rpgmaker
Copy link
Owner

I have not forgotten about your request. Still have not came up with a clever way to use the pointer. And i did not get any reply from you regarding the fix length idea.

@rpgmaker
Copy link
Owner

I got something working now without the upper limit. Just removing the reflection code then it should be good to go.

image

@rpgmaker
Copy link
Owner

Please test and let me know if it works as expected for you then i can publish it as a nuget package. Thanks

@rpgmaker
Copy link
Owner

I think my solution to custom type serializer is more type safe than the way it is done in JSON.net which provides type instead of the concrete object itself.

@jfontsaballs
Copy link
Author

It looks really promising. I'll test it tomorrow when I'm in front of the computer. Thank you very much!

@rpgmaker
Copy link
Owner

I went ahead and published the nuget package already

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

No branches or pull requests

2 participants