0

I'm having an issue with JsonConvert.SerializeObject when I try to serialize my object with:

var statementOfAccount = new
                {
                    main = new 
                    {
                        @xm = "https://api-path.com",
                        RESTHeader = new 
                        {
                            Responsibility = "Responsibility ",
                            RespApplication = "AR",
                            NLSLanguage = "AMERICAN"
                        }
                    }
                };

And giving me:

{
  "main": {
    "xm": "https://api-path.com",
    "RESTHeader": {
      "Responsibility": "Responsibility",
      "RespApplication": "AR",
      "NLSLanguage": "AMERICAN"
    }
  }
}

So basically it's removing the @ from @xm and please note that I can't change the name of the property so I need a solution that will serialize it as is.

wohlstad
  • 12,661
  • 10
  • 26
  • 39
SDEV
  • 77
  • 1
  • 7
  • 6
    I don't think you can do this with an anonymous object - you have to create a class and use the `JsonProperty` attribute I think. – Sweeper Aug 15 '22 at 10:22
  • 3
    https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/verbatim – Jodrell Aug 15 '22 at 10:24
  • @Jodrell Thank you. That's the link I was trying to find. :) – ProgrammingLlama Aug 15 '22 at 10:24
  • 2
    The `@` indicates a verbatim identifier – Jodrell Aug 15 '22 at 10:24
  • You'll need to create the type with a valid c# names, then either, write your own serializer or annotate the type so that your serializer of choice uses the name you want. https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties?pivots=dotnet-6-0 – Jodrell Aug 15 '22 at 10:30
  • 3
    As an alternative to creating a class (if this is a one-off), serializing a dictionary is another possibility, with recent advances in syntax for initializers (`new Dictionary { ["@xm"] = "https://api-path.com", ["RestHeader"] = new { Responsibility = ... }`). Note that dictionaries and anonymous objects can be mixed this way. Of course a class may be preferable anyway for long-term maintainability. – Jeroen Mostert Aug 15 '22 at 10:35
  • 2
    As mentioned, the `@` isn't doing what you think it does. It's not part of the name at all, it's just an escape character. You can't have `@` in a field name, so you'll need to use `JsonProperty`. – Charlieface Aug 15 '22 at 11:01

2 Answers2

1

one way would be to create a custom class instead of using an anonymous

public class Custom
{
....
[JsonProperty["@xm"]
 public string @xm {get; set;}
....
}

since your anonymous object properties are known and can't cause any property overlaping, another way is to replace a json string after serialization

json=json.Replace("xm:","@xm:");
Serge
  • 40,935
  • 4
  • 18
  • 45
  • 1
    The "replace after the fact" strategy is both inefficient and risky, as there's nothing to prevent the string `xm:` from appearing in the output as something other than a property name. Best not go down that path to begin with. – Jeroen Mostert Aug 15 '22 at 11:27
  • @JeroenMostert see my updated answer. And it is radiculous to talk about performance when you have 100 byte string – Serge Aug 15 '22 at 11:29
  • 1
    The problem is not with the properties themselves being known, but that (in real code) you'd expect things like `Responsibility = responsibilityFromUserInput` rather than a fixed string as per the question. If you really knew not only all the properties but also their values at compile time an even simpler way is to just paste in the JSON string verbatim rather than messing around with serialization at all. – Jeroen Mostert Aug 15 '22 at 11:32
  • @JeroenMostert I am assuming that OP put a real code. And I am not offering it as a generic soluition for any cases. Why you don't post your solution? It is always easy to critisize everybody when you can not offer anyting. – Serge Aug 15 '22 at 11:35
  • Or perhaps the attribute should be [JsonPropertyName](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonpropertynameattribute?view=net-6.00) – Jodrell Aug 15 '22 at 11:37
  • My comment is not personal criticism, or at least not intended to be so, but a remark to point out that this technique has the potential to fail in general, which I think would be valuable to readers, especially since answers on SO are read by many people, not just the OP. I'll leave it at that. – Jeroen Mostert Aug 15 '22 at 11:39
  • @Jodrell or perhaps the attribute should be JsonProperty. Pls give a chance to OP owner to try it and to let me know if there is a problem. – Serge Aug 15 '22 at 11:40
  • @JeroenMostert It is not a generic question. There is code that is not working properly and OP asking how to fix it. Why you don't give a chance to OP owner to try it and to let ME know if there is a problem still. I will then offer something else. – Serge Aug 15 '22 at 11:41
  • I would upvote if you hadn't suggested the post replace. – Jodrell Aug 15 '22 at 12:32
  • 1
    @Jodrell Thank you, but I don't need to be upvoted, since I have a plenty of score already. I just try to help people. This is why I became upset, since in many cases OP doesn't appreciate any help, but I have to argue with another users for nothing. – Serge Aug 15 '22 at 13:10
  • @Serge, happens so often. – Jodrell Aug 15 '22 at 13:34
  • @Serge, I really appreciate your help,thank you, but the thing is that I can't upvote any solution since I have less than 15 reputations :( – SDEV Aug 16 '22 at 07:50
1

https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties?pivots=dotnet-6-0

this solved my problem to use JsonPropertyName but with JsonSerializer.Serialize instead of JsonConvert.SerializeObject so the problem was me using an anonymous object as most of you suggested but using JsonPropertyName only worked with JsonSerializer.Serialize, it didn't work with JsonConvert.SerializeObject

solution:

  public class Main
    {
           [JsonPropertyName("@xm")]
            public string @xm { get; set; }
            public RESTHeader RESTHeader { get; set; }
        }

    public class RESTHeader
    {
        public string Responsibility { get; set; }
        public string RespApplication { get; set; }
        public string NLSLanguage { get; set; }
    }

    public class Root
    {
        public Main main { get; set; }
    }


   var statementOfAccount = new Root
                {
                    main = new Main
                    {
                        @xm = "https://api-path",
                        RESTHeader = new RESTHeader
                        {
                            Responsibility = "Responsibility ",
                            RespApplication = "AR",
                            NLSLanguage = "AMERICAN"
                        }
                    }

                };

var json = System.Text.Json.JsonSerializer.Serialize(statementOfAccount);
SDEV
  • 77
  • 1
  • 7
  • The confusion is that `JsonProperty` is for `JSON.Net` serializer and `JsonPropertyName` is for the `System.Text.Json` serializer. – Jodrell Aug 15 '22 at 12:31