.NET 6 System.Text.Json JsonPropertyOrder fails when more than 16 properties

Viewed 574

.NET 6 System.Text.Json serializes properties in order unless it has more than 16 properties and at least 1 property is using the JsonPropertyOrder attribute.

Take the following code:

    using System.Text.Json;
    using System.Text.Json.Serialization;

    internal class Class1
    {
        [JsonPropertyOrder(1)]
        public string One => "1";
        public string Two => "2";
        public string Three => "3";
        public string Four => "4";
        public string Five => "5";
        public string Six => "6";
        public string Seven => "7";
        public string Eight => "8";
        public string Nine => "9";
        public string Ten => "10";
        public string Eleven => "11";
        public string Twelve => "12";
        public string Thirteen => "13";
        public string Fourteen => "14";
        public string Fifteen => "15";
        public string Sixteen => "16";
        //public string Seventeen => "17";
        public string Serialize()
        {
            return JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true});
        }
    }

Calling Serialize produces the following output:

{
  "Two": "2",
  "Three": "3",
  "Four": "4",
  "Five": "5",
  "Six": "6",
  "Seven": "7",
  "Eight": "8",
  "Nine": "9",
  "Ten": "10",
  "Eleven": "11",
  "Twelve": "12",
  "Thirteen": "13",
  "Fourteen": "14",
  "Fifteen": "15",
  "Sixteen": "16",
  "One": "1"
}

Uncomment the following line

public string Seventeen => "17";

and it produces the following output:

{
  "Nine": "9",
  "Fifteen": "15",
  "Fourteen": "14",
  "Thirteen": "13",
  "Twelve": "12",
  "Eleven": "11",
  "Ten": "10",
  "Sixteen": "16",
  "Seventeen": "17",
  "Seven": "7",
  "Six": "6",
  "Five": "5",
  "Four": "4",
  "Three": "3",
  "Two": "2",
  "Eight": "8",
  "One": "1"
}

If you comment out [JsonPropertyOrder(1)], the order comes out correctly.

How can we fix this?

2 Answers

you don't need any [JsonProperty(Order = ..)]. if you want to serialize object prpoperties in a special order, just define them in this order.

 // [JsonPropertyOrder(1)]   remove it from class
 public string One => "1";

When you try to use [JsonPropertyOrder(+number)] with positive numbers, as a matter of fact, properties without this attribute are serialized at first, in a random order, after this properties with this attribute in an attribute order.

if you use [JsonPropertyOrder(-number)] with negative numbers, at first serialized properties with this numbers, after properties without attribute numbers.

So if you want to order all properties in a custom order, you have to put this attribute at each property. Only in this case all your properties will be properly ordered.

Try with JsonConvert.SerializeObject method

public class BaseClass1
            {
               
    
                [JsonProperty(Order = 2)]
                public string First => "F";
                [JsonProperty(Order = 1)]
                public string Last => "L";
            }
    
            internal class Class1 : BaseClass1
            {
                public string One => "1";
                public string Two => "2";
                public string Three => "3";
                [JsonProperty(Order = 3)]
                public string Four => "4";
                public string Five => "5";
                public string Six => "6";
                public string Seven => "7";
                public string Eight => "8";
                public string Nine => "9";
                public string Ten => "10";
                public string Eleven => "11";
                public string Twelve => "12";
                public string Thirteen => "13";
                public string Fourteen => "14";
                public string Fifteen => "15";
    
                public string Serialize()
                {
                    //return JsonSerializer.Serialize(this, new JsonSerializerOptions() { WriteIndented = true });
                    return JsonConvert.SerializeObject(this, Formatting.Indented);
                }
            }
Related