// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using System.Dynamic; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Helpers.Test { public class JsonTest { [Fact] public void EncodeWithDynamicObject() { // Arrange dynamic obj = new DummyDynamicObject(); obj.Name = "Hello"; obj.Age = 1; obj.Grades = new[] { "A", "B", "C" }; // Act string json = Json.Encode(obj); // Assert Assert.Equal("{\"Name\":\"Hello\",\"Age\":1,\"Grades\":[\"A\",\"B\",\"C\"]}", json); } [Fact] public void EncodeArray() { // Arrange object input = new string[] { "one", "2", "three", "4" }; // Act string json = Json.Encode(input); // Assert Assert.Equal("[\"one\",\"2\",\"three\",\"4\"]", json); } [Fact] public void EncodeDynamicJsonArrayEncodesAsArray() { // Arrange dynamic array = Json.Decode("[1,2,3]"); // Act string json = Json.Encode(array); // Assert Assert.Equal("[1,2,3]", json); } [Fact] public void DecodeDynamicObject() { // Act var obj = Json.Decode("{\"Name\":\"Hello\",\"Age\":1,\"Grades\":[\"A\",\"B\",\"C\"]}"); // Assert Assert.Equal("Hello", obj.Name); Assert.Equal(1, obj.Age); Assert.Equal(3, obj.Grades.Length); Assert.Equal("A", obj.Grades[0]); Assert.Equal("B", obj.Grades[1]); Assert.Equal("C", obj.Grades[2]); } [Fact] public void DecodeDynamicObjectImplicitConversionToDictionary() { // Act IDictionary values = Json.Decode("{\"Name\":\"Hello\",\"Age\":1}"); // Assert Assert.Equal("Hello", values["Name"]); Assert.Equal(1, values["Age"]); } [Fact] public void DecodeArrayImplicitConversionToArrayAndObjectArray() { // Act Array array = Json.Decode("[1,2,3]"); object[] objArray = Json.Decode("[1,2,3]"); IEnumerable dynamicEnumerable = Json.Decode("[{a:1}]"); // Assert Assert.NotNull(array); Assert.NotNull(objArray); Assert.NotNull(dynamicEnumerable); } [Fact] public void DecodeArrayImplicitConversionToArrayArrayValuesAreDynamic() { // Act dynamic[] objArray = Json.Decode("[{\"A\":1}]"); // Assert Assert.NotNull(objArray); Assert.Equal(1, objArray[0].A); } [Fact] public void DecodeDynamicObjectAccessPropertiesByIndexer() { // Arrange var obj = Json.Decode("{\"Name\":\"Hello\",\"Age\":1,\"Grades\":[\"A\",\"B\",\"C\"]}"); // Assert Assert.Equal("Hello", obj["Name"]); Assert.Equal(1, obj["Age"]); Assert.Equal(3, obj["Grades"].Length); Assert.Equal("A", obj["Grades"][0]); Assert.Equal("B", obj["Grades"][1]); Assert.Equal("C", obj["Grades"][2]); } [Fact] public void DecodeDynamicObjectAccessPropertiesByNullIndexerReturnsNull() { // Arrange var obj = Json.Decode("{\"Name\":\"Hello\",\"Age\":1,\"Grades\":[\"A\",\"B\",\"C\"]}"); // Assert Assert.Null(obj[null]); } [Fact] public void DecodeDateTime() { // Act DateTime dateTime = Json.Decode("\"\\/Date(940402800000)\\/\""); // Assert Assert.Equal(1999, dateTime.Year); Assert.Equal(10, dateTime.Month); Assert.Equal(20, dateTime.Day); } [Fact] public void DecodeNumber() { // Act int number = Json.Decode("1"); // Assert Assert.Equal(1, number); } [Fact] public void DecodeString() { // Act string @string = Json.Decode("\"1\""); // Assert Assert.Equal("1", @string); } [Fact] public void DecodeArray() { // Act var values = Json.Decode("[11,12,13,14,15]"); // Assert Assert.Equal(5, values.Length); Assert.Equal(11, values[0]); Assert.Equal(12, values[1]); Assert.Equal(13, values[2]); Assert.Equal(14, values[3]); Assert.Equal(15, values[4]); } [Fact] public void DecodeObjectWithArrayProperty() { // Act var obj = Json.Decode("{\"A\":1,\"B\":[1,3,4]}"); object[] bValues = obj.B; // Assert Assert.Equal(1, obj.A); Assert.Equal(1, bValues[0]); Assert.Equal(3, bValues[1]); Assert.Equal(4, bValues[2]); } [Fact] public void DecodeArrayWithObjectValues() { // Act var obj = Json.Decode("[{\"A\":1},{\"B\":3, \"C\": \"hello\"}]"); // Assert Assert.Equal(2, obj.Length); Assert.Equal(1, obj[0].A); Assert.Equal(3, obj[1].B); Assert.Equal("hello", obj[1].C); } [Fact] public void DecodeArraySetValues() { // Arrange var values = Json.Decode("[1,2,3,4,5]"); for (int i = 0; i < values.Length; i++) { values[i]++; } // Assert Assert.Equal(5, values.Length); Assert.Equal(2, values[0]); Assert.Equal(3, values[1]); Assert.Equal(4, values[2]); Assert.Equal(5, values[3]); Assert.Equal(6, values[4]); } [Fact] public void DecodeArrayPassToMethodThatTakesArray() { // Arrange var values = Json.Decode("[3,2,1]"); // Act int index = Array.IndexOf(values, 2); // Assert Assert.Equal(1, index); } [Fact] public void DecodeArrayGetEnumerator() { // Arrange var values = Json.Decode("[1,2,3]"); // Assert int val = 1; foreach (var value in values) { Assert.Equal(val, val); val++; } } [Fact] public void DecodeObjectPropertyAccessIsSameObjectInstance() { // Arrange var obj = Json.Decode("{\"Name\":{\"Version:\":4.0, \"Key\":\"Key\"}}"); // Assert Assert.Same(obj.Name, obj.Name); } [Fact] public void DecodeArrayAccessingMembersThatDontExistReturnsNull() { // Act var obj = Json.Decode("[\"a\", \"b\"]"); // Assert Assert.Null(obj.PropertyThatDoesNotExist); } [Fact] public void DecodeObjectSetProperties() { // Act var obj = Json.Decode("{\"A\":{\"B\":100}}"); obj.A.B = 20; // Assert Assert.Equal(20, obj.A.B); } [Fact] public void DecodeObjectSettingObjectProperties() { // Act var obj = Json.Decode("{\"A\":1}"); obj.A = new { B = 1, D = 2 }; // Assert Assert.Equal(1, obj.A.B); Assert.Equal(2, obj.A.D); } [Fact] public void DecodeObjectWithArrayPropertyPassPropertyToMethodThatTakesArray() { // Arrange var obj = Json.Decode("{\"A\":[3,2,1]}"); // Act Array.Sort(obj.A); // Assert Assert.Equal(1, obj.A[0]); Assert.Equal(2, obj.A[1]); Assert.Equal(3, obj.A[2]); } [Fact] public void DecodeObjectAccessingMembersThatDontExistReturnsNull() { // Act var obj = Json.Decode("{\"A\":1}"); // Assert Assert.Null(obj.PropertyThatDoesntExist); } [Fact] public void DecodeObjectWithSpecificType() { // Act var person = Json.Decode("{\"Name\":\"David\", \"Age\":2}"); // Assert Assert.Equal("David", person.Name); Assert.Equal(2, person.Age); } [Fact] public void DecodeObjectWithImplicitConversionToNonDynamicTypeThrows() { // Act & Assert Assert.Throws(() => { Person person = Json.Decode("{\"Name\":\"David\", \"Age\":2, \"Address\":{\"Street\":\"Bellevue\"}}"); }, "Unable to convert to \"System.Web.Helpers.Test.JsonTest+Person\". Use Json.Decode instead."); } private class DummyDynamicObject : DynamicObject { private IDictionary _values = new Dictionary(); public override IEnumerable GetDynamicMemberNames() { return _values.Keys; } public override bool TrySetMember(SetMemberBinder binder, object value) { _values[binder.Name] = value; return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { return _values.TryGetValue(binder.Name, out result); } } private class Person { public string Name { get; set; } public int Age { get; set; } public int GPA { get; set; } public Address Address { get; set; } } private class Address { public string Street { get; set; } } } }