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

System.Text.Json Serialize return weird result #46869

Closed
thanhhn253 opened this issue Jan 9, 2021 · 8 comments
Closed

System.Text.Json Serialize return weird result #46869

thanhhn253 opened this issue Jan 9, 2021 · 8 comments
Assignees
Labels
area-System.Text.Json untriaged New issue has not been triaged by the area owner

Comments

@thanhhn253
Copy link

Please have a look at the following code:
`using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ConsoleApp7
{
public class a
{
public int b { get; set; }
public List<e> c { get; set; }
public a my_a { get; set; }
}
public class e
{
public int d { get; set; }
public string g { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var data = new a { b = 1, c = new List<e> { new e { d = 4, g = "test" } } };
        data.my_a = data;
        var json_options = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.Preserve, WriteIndented = true };
        Console.WriteLine(JsonSerializer.Serialize(data, json_options));
    }
}

}
`

The output:
{ "$id": "1", "b": 1, "c": { "$id": "2", "$values": [ { "$id": "3", "d": 4, "g": "test" } ] }, "my_a": { "$ref": "1" } }

Look at the c array in the output string. What the hell is that? Array became object?
Please, this is disgusting
Please provide ReferenceHandler.Ignore
ReferenceHandler.Preserve is stupid

@wli3 wli3 transferred this issue from dotnet/sdk Jan 12, 2021
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Jan 12, 2021
@Clockwork-Muse
Copy link
Contributor

Clockwork-Muse commented Jan 12, 2021

ReferenceHandler.Preserve is attempting to take care of the case where there might be a duplicate reference to the same list (or a self-reference, since a List<object> can contain a reference to itself), and so, rather than output the contents twice, you'd end up with a reference to the earlier output list. That is, you'd end up with something like:

{
  "$id": "1",
  "b": 1,
  "c": {
    "$id": "2",
    "$values": [
      {
        "$id": "3",
        "d": 4,
        "g": "test"
      }
    ]
  },
  "c_copy": {
    "$ref": "2"
  },
  "my_a": {
    "$ref": "1"
  }
}

Note that since you need Preserve to deal with your object's cyclical graph, you're going to need a compliant reader on the other end that can handle the $refs anyways (ie, you can't expect one without that ability to correctly parse and reconstruct the objects regardless).

@thanhhn253
Copy link
Author

We rolled back to Newtonsoft. Thank you

@thanhhn253
Copy link
Author

You have your own logic. But we cannot use that.
What happen if a Java or Python guy call your api and revieve that
That is not a normal json anymore

@Clockwork-Muse
Copy link
Contributor

.... what are you talking about, it's perfectly valid JSON?

What's not "normal" is the use of the various id links. You'd have to tell Java/Python to handle them (and I would bet there are already libraries to do so). That said, usually you don't have duplicate objects/circular references, so you just serialize everything by value.

@thanhhn253
Copy link
Author

Why didn't you give me ReferenceHandler.Ignore option?
I need a way to bypass the ref loop but still maintain the structure of the class
That is why I switched back to Newtonsoft
Why is there only one option?
Please give us more options to choose

@Clockwork-Muse
Copy link
Contributor

I need a way to bypass the ref loop but still maintain the structure of the class

That's not what your issue is currently filed as (referencing the way lists are serialized vs how cyclical graphs are handled).

Now that it's more obvious what you actually want, you want to file an API request. Note that the equivalent behavior in Newtonsoft is handled via a completely separate option, ReferenceLoopHandling (and not PreserveReferences), and should probably also be handled as a separate option here, if we decide to add it.

Why is there only one option?
Please give us more options to choose

Probably because this might be the first time anybody has asked for this behavior.

@thanhhn253
Copy link
Author

thanhhn253 commented Jan 15, 2021

"That's not what your issue is currently filed as"
Are you sure? You convert an array to an json object. You change the structure. Everyone, who paste your json will recieve object not an array. Did you read the first post?

"this might be the first time anybody has asked for this behavior"
What are you talking about?
This is stupid
I dont want to waste time here anymore. Good bye

@svick
Copy link
Contributor

svick commented Jan 15, 2021

Why didn't you give me ReferenceHandler.Ignore option?

That's #40099, which has already been approved and should be included in .Net 6.0.

@ghost ghost locked as resolved and limited conversation to collaborators Feb 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

5 participants