title: Json.Net not serializing decimals the same way twice
body: <p>I was testing Json.NET serialization of a shopping cart I'm working on and noticed that when I serialize -> deserialize -> serialize again, I'm getting a difference in the trailing zero formatting of some of the <code>decimal</code> fields. Here is the serialization code:</p>
  
  <pre><code>private static void TestRoundTripCartSerialization(Cart cart)
  {
      string cartJson = JsonConvert.SerializeObject(cart, Formatting.Indented);
  
      Console.WriteLine(cartJson);
  
      Cart cartClone = JsonConvert.DeserializeObject&lt;Cart&gt;(cartJson);
  
      string cloneJson = JsonConvert.SerializeObject(cartClone, Formatting.Indented);
  
      Console.WriteLine(cloneJson);
  
      Console.WriteLine("\r\n Serialized carts are " + (cartJson == cloneJson ? "" : "not") + " identical");
  }
  </code></pre>
  
  <p>The <code>Cart</code> implements <code>IEnumerable&lt;T&gt;</code> and has a <code>JsonObjectAttribute</code> to allow it to serialize as an object, including its properties as well as its inner list. The <code>decimal</code> properties of <code>Cart</code> do not change, but some of the <code>decimal</code> properties of objects and their inner objects in the inner list/array do as in this excerpt from output of the code above:</p>
  
  <p>First time serializing:</p>
  
  <pre><code>      ...
        "Total": 27.0000,
        "PaymentPlan": {
          "TaxRate": 8.00000,
          "ManualDiscountApplied": 0.0,
          "AdditionalCashDiscountApplied": 0.0,
          "PreTaxDeposit": 25.0000,
          "PreTaxBalance": 0.0,
          "DepositTax": 2.00,
          "BalanceTax": 0.0,
          "SNPFee": 25.0000,
          "cartItemPaymentPlanTypeID": "SNP",
          "unitPreTaxTotal": 25.0000,
          "unitTax": 2.00
        }
      }
    ],
   }
  </code></pre>
  
  <p>Second time serializing:</p>
  
  <pre><code>      ...
        "Total": 27.0,
        "PaymentPlan": {
          "TaxRate": 8.0,
          "ManualDiscountApplied": 0.0,
          "AdditionalCashDiscountApplied": 0.0,
          "PreTaxDeposit": 25.0,
          "PreTaxBalance": 0.0,
          "DepositTax": 2.0,
          "BalanceTax": 0.0,
          "SNPFee": 25.0,
          "cartItemPaymentPlanTypeID": "SNP",
          "unitPreTaxTotal": 25.0,
          "unitTax": 2.0
        }
      }
    ],
   }
  </code></pre>
  
  <p>Notice the <code>Total</code>, <code>TaxRate</code>, and some of the others have changed from four trailing zeroes to a single trailing zero. I did find some stuff regarding changes to handling of trailing zeroes in the source code at one point, but nothing that I understood well enough to put together with this. I can't share the full Cart implementation here, but I built a bare bones model of it and couldn't reproduce the results. The most obvious differences were my bare bones version lost some additional inheritance/implementation of abstract base classes and interfaces and some generic type usage on those (where the generic type param defines the type of some of the nested child objects). </p>
  
  <p>So I'm hoping without that someone can still answer: Any idea why the trailing zeroes change? The objects appear to be identical to the original after deserializing either JSON string, but I want to be sure there isn't something in Json.NET that causes a loss of precision or rounding that may gradually change one of these decimals after many serialization round trips.</p>
  
  <hr>
  
  <p><strong>Updated</strong></p>
  
  <p>Here's a reproducible example. I thought I had ruled out the <code>JsonConverter</code> but was mistaken. Because my inner <code>_items</code> list is typed on an interface, I have to tell Json.NET which concrete type to deserialize back to. I didn't want the actual <code>Type</code> names in the JSON so rather than using <code>TypeNameHandling.Auto</code>, I've given the items a unique string identifier property. The <code>JsonConverter</code> uses that to choose a concrete type to create, but I guess the <code>JObject</code> has already parsed my <code>decimal</code>s to <code>double</code>s? This is maybe my 2nd time implementing a <code>JsonConverter</code> and I don't have a complete understanding of how they work because finding documentation has been difficult. So I may have <code>ReadJson</code> all wrong.</p>
  
  <pre><code>[JsonObject]
  public class Test : IEnumerable&lt;IItem&gt;
  {
      [JsonProperty(ItemConverterType = typeof(TestItemJsonConverter))]
      protected List&lt;IItem&gt; _items;
  
      public Test() { }
  
      [JsonConstructor]
      public Test(IEnumerable&lt;IItem&gt; o)
      {
          _items = o == null ? new List&lt;IItem&gt;() : new List&lt;IItem&gt;(o);
      }
  
      public decimal Total { get; set; }
  
      IEnumerator IEnumerable.GetEnumerator()
      {
          return _items.GetEnumerator();
      }
  
      IEnumerator&lt;IItem&gt; IEnumerable&lt;IItem&gt;.GetEnumerator()
      {
          return _items.GetEnumerator();
      }
  }
  
  public interface IItem
  {
      string ItemName { get; }
  }
  
  public class Item1 : IItem
  {
      public Item1() { }
      public Item1(decimal fee) { Fee = fee; }
  
      public string ItemName { get { return "Item1"; } }
  
      public virtual decimal Fee { get; set; }
  }
  
  public class TestItemJsonConverter : JsonConverter
  {
      public override bool CanConvert(Type objectType) { return (objectType == typeof(IItem)); }
  
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
          object result = null;
  
          JObject jObj = JObject.Load(reader);
  
          string itemTypeID = jObj["ItemName"].Value&lt;string&gt;();
  
          //NOTE: My real implementation doesn't have hard coded strings or types here.
          //See the code block below for actual implementation.
          if (itemTypeID == "Item1")
              result = jObj.ToObject(typeof(Item1), serializer);
  
          return result;
      }
  
      public override bool CanWrite { get { return false; } }
  
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); }
  }
  
  class Program
  {
      static void Main(string[] args)
      {
          Test test1 = new Test(new List&lt;Item1&gt; { new Item1(9.00m), new Item1(24.0000m) })
          {
              Total = 33.0000m
          };
  
          string json = JsonConvert.SerializeObject(test1, Formatting.Indented);
          Console.WriteLine(json);
          Console.WriteLine();
  
          Test test1Clone = JsonConvert.DeserializeObject&lt;Test&gt;(json);
          string json2 = JsonConvert.SerializeObject(test1Clone, Formatting.Indented);
          Console.WriteLine(json2);
  
          Console.ReadLine();
      }
  }
  </code></pre>
  
  <p>Snippet from my actual converter:</p>
  
  <pre><code>if (CartItemTypes.TypeMaps.ContainsKey(itemTypeID))
      result = jObj.ToObject(CartItemTypes.TypeMaps[itemTypeID], serializer);
  </code></pre>