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

Add PATCH mode for JSON deserialization #47841

Closed
kingcean opened this issue Feb 4, 2021 · 5 comments
Closed

Add PATCH mode for JSON deserialization #47841

kingcean opened this issue Feb 4, 2021 · 5 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json

Comments

@kingcean
Copy link

kingcean commented Feb 4, 2021

Background and Motivation

For most scenarios, we will deserialize a JSON object to a new object in .NET. But for some others, we may just need patch the memberwise delta changes to an existing object from the JSON properties. That means we may already have an object with properties initialized or set by other places, and we can still have a way to continue to set a number of specific properties from a JSON object.

Proposed API

namespace System.Text.Json
{
    public static class JsonSerializer
    {
        public static object Deserialize(string json, Type returnType, JsonSerializerOptions options = null);
        public static object Deserialize(ReadOnlySpan<byte> utf8Json, Type returnType, JsonSerializerOptions options = null);
        public static object Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(string json, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(ReadOnlySpan<byte> utf8Json, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(ref Utf8JsonReader reader, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, string json, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, ReadOnlySpan<byte> utf8Json, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize<TValue>(TValue value, string json, JsonSerializerOptions options = null) where TValue : class;
+       public static void PatchDeserialize<TValue>(TValue value, ReadOnlySpan<byte> utf8Json, JsonSerializerOptions options = null) where TValue : class;
+       public static void PatchDeserialize<TValue>(TValue value, ref Utf8JsonReader reader, JsonSerializerOptions options = null) where TValue : class;
        public static string Serialize(object value, Type inputType, JsonSerializerOptions options = null);
        public static void Serialize(Utf8JsonWriter writer, object value, Type inputType, JsonSerializerOptions options = null);
        public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null);
        public static void Serialize<TValue>(Utf8JsonWriter writer, Type inputType, JsonSerializerOptions options = null);
        public static Task SerializeAsync(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options = null);
        public static void SerializeAsync<TValue>(Stream utf8Json, TValue value, JsonSerializerOptions options = null);
        public static byte[] SerializeToUtf8Bytes(object value, Type inputType, JsonSerializerOptions options = null);
        public static byte[] SerializeToUtf8Bytes<TValue>(TValue value, JsonSerializerOptions options = null);
    }
}

The static methods PatchDeserialize are used to delta update the object with the JSON data.

Usage Examples

public class Model
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string Other { get; set; }
    public string TestForNull { get; set; }
}
var json = "{ \"Name\": \"Abcdefg\", \"Value\": \"Hijklmn\", \"TestForNull\": null }";
var m = new Model
{
    Name = "Opq Rst",
    Other = "Uvw Xyz",
    TestForNull = "0123456789"
};
JsonSerializer.PatchDeserialize(m, json);

Assert.AreEqual("Abcdefg", m.Name);
Assert.AreEqual("Hijklmn", m.Value);
Assert.AreEqual("Uvw Xyz", m.Other);
Assert.IsNull(m.TestForNull);
@kingcean kingcean added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Feb 4, 2021
@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Feb 4, 2021
@ghost
Copy link

ghost commented Feb 4, 2021

Tagging subscribers to this area: @eiriktsarpalis, @layomia
See info in area-owners.md if you want to be subscribed.

Issue Details

Background and Motivation

For most scenarios, we will deserialize a JSON object to a new object in .NET. But for some others, we may just need patch the memberwise delta changes to an existing object from the JSON properties. That means we may already have an object with properties initialized or set by other places, and we can still have a way to continue to set a number of specific properties from a JSON object.

Proposed API

namespace System.Text.Json
{
    public static class JsonSerializer
    {
        public static object Deserialize(string json, Type returnType, JsonSerializerOptions options = null);
        public static object Deserialize(ReadOnlySpan<byte> utf8Json, Type returnType, JsonSerializerOptions options = null);
        public static object Deserialize(ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(string json, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(ReadOnlySpan<byte> utf8Json, JsonSerializerOptions options = null);
        public static TValue Deserialize<TValue>(ref Utf8JsonReader reader, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, string json, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, ReadOnlySpan<byte> utf8Json, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize(object value, ref Utf8JsonReader reader, Type returnType, JsonSerializerOptions options = null);
+       public static void PatchDeserialize<TValue>(TValue value, string json, JsonSerializerOptions options = null) where TValue : class;
+       public static void PatchDeserialize<TValue>(TValue value, ReadOnlySpan<byte> utf8Json, JsonSerializerOptions options = null) where TValue : class;
+       public static void PatchDeserialize<TValue>(TValue value, ref Utf8JsonReader reader, JsonSerializerOptions options = null) where TValue : class;
        public static string Serialize(object value, Type inputType, JsonSerializerOptions options = null);
        public static void Serialize(Utf8JsonWriter writer, object value, Type inputType, JsonSerializerOptions options = null);
        public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null);
        public static void Serialize<TValue>(Utf8JsonWriter writer, Type inputType, JsonSerializerOptions options = null);
        public static Task SerializeAsync(Stream utf8Json, object value, Type inputType, JsonSerializerOptions options = null);
        public static void SerializeAsync<TValue>(Stream utf8Json, TValue value, JsonSerializerOptions options = null);
        public static byte[] SerializeToUtf8Bytes(object value, Type inputType, JsonSerializerOptions options = null);
        public static byte[] SerializeToUtf8Bytes<TValue>(TValue value, JsonSerializerOptions options = null);
    }
}

The static methods PatchDeserialize are used to delta update the object with the JSON data.

Usage Examples

public class Model
{
    public string Name { get; set; }
    public string Value { get; set; }
    public string Other { get; set; }
    public string TestForNull { get; set; }
}
var json = "{ \"Name\": \"Abcdefg\", \"Value\": \"Hijklmn\", \"TestForNull\": null }";
var m = new Model
{
    Name = "Opq Rst",
    Other = "Uvw Xyz",
    TestForNull = "0123456789"
};
JsonSerializer.PatchDeserialize(m, json);

Assert.AreEqual("Abcdefg", m.Name);
Assert.AreEqual("Hijklmn", m.Value);
Assert.AreEqual("Uvw Xyz", m.Other);
Assert.IsNull(m.TestForNull);
Author: kingcean
Assignees: -
Labels:

api-suggestion, area-System.Text.Json, untriaged

Milestone: -

@eiriktsarpalis
Copy link
Member

Hi @kingcean, that's an interesting proposal. I don't believe I've seen such a feature before, do you know of any serializer libraries that already offer this?

@kingcean
Copy link
Author

kingcean commented Feb 4, 2021

Hi @eiriktsarpalis , No. But I think it will be very useful when we build a web service and provide an API so that the client just need to PUT the delta update (only the properties needed to change) in the payload of the HTTP request to modify the entity in database.

@layomia
Copy link
Contributor

layomia commented Feb 4, 2021

I believe this is a duplicate of #29538.

@eiriktsarpalis
Copy link
Member

In that case, I'm going to close this one. @kingcean feel free to continue the conversation over in #29538.

@layomia layomia removed the untriaged New issue has not been triaged by the area owner label Feb 4, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Mar 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Text.Json
Projects
None yet
Development

No branches or pull requests

3 participants