Skip to content

Commit bdc436d

Browse files
committed
- Fixed #229
Signed-off-by: rpgmaker <olamide.bakre@gmail.com>
1 parent 9364b37 commit bdc436d

File tree

10 files changed

+133
-53
lines changed

10 files changed

+133
-53
lines changed

NetJSON.Tests/SerializeTests.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,43 @@ public void ShouldThrowErrorForInvalidDictionaryJSONNoQuote()
17961796

17971797
Assert.IsNotNull(exception, "Should throw invalid json exception");
17981798
}
1799+
1800+
[TestMethod]
1801+
public void ShouldSerializeDeserializeAutoPropertyWithObjectInitializer()
1802+
{
1803+
var myObject2 = new SimpleObject2() { ID = 0, Name = "Test", Value = "Value" };
1804+
var json2 = NetJSON.Serialize(myObject2, new NetJSONSettings() { SkipDefaultValue = false });
1805+
var recreatedObject2 = NetJSON.Deserialize<SimpleObject2>(json2, new NetJSONSettings() { SkipDefaultValue = false });
1806+
Assert.AreEqual(myObject2.ID, recreatedObject2.ID);
1807+
}
1808+
1809+
[TestMethod]
1810+
public void ShouldSerializeDeserializeDefaultPropertyInConstructorWithObjectInitializer()
1811+
{
1812+
var myObject3 = new SimpleObject3() { ID = 0, Name = "Test", Value = "Value" };
1813+
var json3 = NetJSON.Serialize(myObject3);
1814+
var recreatedObject3 = NetJSON.Deserialize<SimpleObject3>(json3);
1815+
Assert.AreEqual(5, recreatedObject3.ID);
1816+
}
1817+
}
1818+
1819+
public class SimpleObject3
1820+
{
1821+
public SimpleObject3()
1822+
{
1823+
ID = 5;
1824+
}
1825+
1826+
public int ID { get; set; }
1827+
public string Name { get; set; }
1828+
public string Value { get; set; }
1829+
}
1830+
1831+
public class SimpleObject2
1832+
{
1833+
public int ID { get; set; } = -5;
1834+
public string Name { get; set; }
1835+
public string Value { get; set; }
17991836
}
18001837

18011838
public class Dummy

NetJSON/NetJSON.cs

Lines changed: 92 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,13 +4444,15 @@ private static void GenerateTypeSetValueFor(TypeBuilder typeBuilder, Type type,
44444444
// il.Emit(OpCodes.Pop);
44454445
// }
44464446
//} else il.Emit(OpCodes.Stfld, field);
4447-
} else {
4447+
} else
4448+
{
44484449
var propValue = il.DeclareLocal(originPropType);
44494450
var isValueType = propType.GetTypeInfo().IsValueType;
44504451
var isPrimitiveType = propType.IsPrimitiveType();
44514452
var isStruct = isValueType && !isPrimitiveType;
44524453
var isBool = propType == _boolType;
44534454
var propNullLabel = !isNullable && !isBool ? il.DefineLabel() : default(Label);
4455+
var skipDefaultFalseLabel = !isNullable && !isBool ? il.DefineLabel() : default(Label);
44544456
var hasPropLabel = propNullLabel != default(Label);
44554457
var nullablePropValue = isNullable ? il.DeclareLocal(originPropType) : null;
44564458
var equalityMethod = propType.GetMethod("op_Equality");
@@ -4463,24 +4465,35 @@ private static void GenerateTypeSetValueFor(TypeBuilder typeBuilder, Type type,
44634465

44644466
il.Emit(OpCodes.Stloc, propValue);
44654467

4466-
if (hasPropLabel) {
4468+
if (hasPropLabel)
4469+
{
44674470
if (isStruct)
44684471
il.Emit(OpCodes.Ldloca, propValue);
44694472
else
44704473
il.Emit(OpCodes.Ldloc, propValue);
44714474

4472-
if (isValueType && isPrimitiveType) {
4475+
if (isValueType && isPrimitiveType)
4476+
{
44734477
LoadDefaultValueByType(il, propType);
4474-
} else {
4478+
}
4479+
else
4480+
{
44754481
if (!isValueType)
44764482
il.Emit(OpCodes.Ldnull);
44774483
}
44784484

4479-
if (equalityMethod != null) {
4485+
if (equalityMethod != null)
4486+
{
44804487
il.Emit(OpCodes.Call, equalityMethod);
44814488
il.Emit(OpCodes.Brtrue, propNullLabel);
4482-
} else {
4483-
if (isStruct) {
4489+
il.Emit(OpCodes.Ldarg, 4);
4490+
il.Emit(OpCodes.Callvirt, _settingsSkipDefaultValue);
4491+
il.Emit(OpCodes.Brfalse, propNullLabel);
4492+
}
4493+
else
4494+
{
4495+
if (isStruct)
4496+
{
44844497

44854498
var tempValue = il.DeclareLocal(propType);
44864499

@@ -4493,57 +4506,37 @@ private static void GenerateTypeSetValueFor(TypeBuilder typeBuilder, Type type,
44934506
il.Emit(OpCodes.Callvirt, _objectEquals);
44944507

44954508
il.Emit(OpCodes.Brtrue, propNullLabel);
4496-
4497-
} else
4498-
il.Emit(OpCodes.Beq, propNullLabel);
4499-
}
4500-
}
4501-
4502-
il.Emit(OpCodes.Ldarg_2);
4503-
il.Emit(OpCodes.Ldloc, propValue);
4504-
//if (isNullable) {
4505-
// il.Emit(OpCodes.Newobj, _nullableType.MakeGenericType(propType).GetConstructor(new[] { propType }));
4506-
//}
4507-
4508-
if (isProp) {
4509-
if (setter != null) {
4510-
if (!setter.IsPublic) {
4511-
if (propType.GetTypeInfo().IsValueType)
4512-
il.Emit(OpCodes.Box, isNullable ? prop.PropertyType : propType);
4513-
il.Emit(OpCodes.Ldtoken, setter);
4514-
il.Emit(OpCodes.Call, _methodGetMethodFromHandle);
4515-
il.Emit(OpCodes.Call, _setterPropertyValueMethod.MakeGenericMethod(type));
4516-
} else
4517-
il.Emit(isTypeValueType ? OpCodes.Call : OpCodes.Callvirt, setter);
4518-
} else {
4519-
var setField = type.GetField($"<{propName}>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);
4520-
if (setField == null)
4521-
{
4522-
//TODO: Use IL body and field token from prop.GetGetMethod().GetMethodBody()
4523-
setField = fields.FirstOrDefault(x => x.Name.EndsWith(propName, StringComparison.OrdinalIgnoreCase));
4524-
}
4525-
4526-
if (setField != null)
4527-
{
4528-
if (propType.GetTypeInfo().IsValueType)
4529-
il.Emit(OpCodes.Box, propType);
4530-
il.Emit(OpCodes.Ldtoken, setField);
4531-
il.Emit(OpCodes.Call, _methodGetFieldFromHandle);
4532-
il.Emit(OpCodes.Call, _setterFieldValueMethod.MakeGenericMethod(type));
4509+
il.Emit(OpCodes.Ldarg, 4);
4510+
il.Emit(OpCodes.Callvirt, _settingsSkipDefaultValue);
4511+
il.Emit(OpCodes.Brfalse, propNullLabel);
45334512
}
45344513
else
45354514
{
4536-
il.Emit(OpCodes.Pop);
4537-
il.Emit(OpCodes.Pop);
4515+
il.Emit(OpCodes.Beq, propNullLabel);
4516+
il.Emit(OpCodes.Ldarg, 4);
4517+
il.Emit(OpCodes.Callvirt, _settingsSkipDefaultValue);
4518+
il.Emit(OpCodes.Brfalse, propNullLabel);
45384519
}
45394520
}
4521+
}
45404522

4541-
} else il.Emit(OpCodes.Stfld, field);
4542-
4543-
il.Emit(OpCodes.Ret);
4523+
SetClassMemberValue(type, isTypeValueType, il, fields, prop, field, setter, isProp, propName, propType, isNullable, propValue);
45444524

45454525
if (hasPropLabel)
4526+
{
45464527
il.MarkLabel(propNullLabel);
4528+
}
4529+
4530+
if (hasPropLabel)
4531+
{
4532+
il.Emit(OpCodes.Ldarg, 4);
4533+
il.Emit(OpCodes.Callvirt, _settingsSkipDefaultValue);
4534+
il.Emit(OpCodes.Brtrue, skipDefaultFalseLabel);
4535+
4536+
SetClassMemberValue(type, isTypeValueType, il, fields, prop, field, setter, isProp, propName, propType, isNullable, propValue);
4537+
4538+
il.MarkLabel(skipDefaultFalseLabel);
4539+
}
45474540
}
45484541

45494542
il.Emit(OpCodes.Ret);
@@ -4557,6 +4550,56 @@ private static void GenerateTypeSetValueFor(TypeBuilder typeBuilder, Type type,
45574550
il.Emit(OpCodes.Call, _skipProperty);
45584551
}
45594552

4553+
private static void SetClassMemberValue(Type type, bool isTypeValueType, ILGenerator il, FieldInfo[] fields, PropertyInfo prop, FieldInfo field, MethodInfo setter, bool isProp, string propName, Type propType, bool isNullable, LocalBuilder propValue)
4554+
{
4555+
il.Emit(OpCodes.Ldarg_2);
4556+
il.Emit(OpCodes.Ldloc, propValue);
4557+
4558+
if (isProp)
4559+
{
4560+
if (setter != null)
4561+
{
4562+
if (!setter.IsPublic)
4563+
{
4564+
if (propType.GetTypeInfo().IsValueType)
4565+
il.Emit(OpCodes.Box, isNullable ? prop.PropertyType : propType);
4566+
il.Emit(OpCodes.Ldtoken, setter);
4567+
il.Emit(OpCodes.Call, _methodGetMethodFromHandle);
4568+
il.Emit(OpCodes.Call, _setterPropertyValueMethod.MakeGenericMethod(type));
4569+
}
4570+
else
4571+
il.Emit(isTypeValueType ? OpCodes.Call : OpCodes.Callvirt, setter);
4572+
}
4573+
else
4574+
{
4575+
var setField = type.GetField($"<{propName}>k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance);
4576+
if (setField == null)
4577+
{
4578+
//TODO: Use IL body and field token from prop.GetGetMethod().GetMethodBody()
4579+
setField = fields.FirstOrDefault(x => x.Name.EndsWith(propName, StringComparison.OrdinalIgnoreCase));
4580+
}
4581+
4582+
if (setField != null)
4583+
{
4584+
if (propType.GetTypeInfo().IsValueType)
4585+
il.Emit(OpCodes.Box, propType);
4586+
il.Emit(OpCodes.Ldtoken, setField);
4587+
il.Emit(OpCodes.Call, _methodGetFieldFromHandle);
4588+
il.Emit(OpCodes.Call, _setterFieldValueMethod.MakeGenericMethod(type));
4589+
}
4590+
else
4591+
{
4592+
il.Emit(OpCodes.Pop);
4593+
il.Emit(OpCodes.Pop);
4594+
}
4595+
}
4596+
4597+
}
4598+
else il.Emit(OpCodes.Stfld, field);
4599+
4600+
il.Emit(OpCodes.Ret);
4601+
}
4602+
45604603
private static MethodInfo GenerateCreateListFor(TypeBuilder typeBuilder, Type type) {
45614604
MethodInfo method;
45624605
var key = string.Concat(type.FullName, typeBuilder == null ? Dynamic : string.Empty);

NetJSON/NetJSON.nuspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
<id>NetJSON</id>
55
<title>NetJSON</title>
66
<tags>json json-serializer javascript JSON serializer binary</tags>
7-
<version>1.3.4</version>
7+
<version>1.3.5</version>
88
<authors>TJ Bakre</authors>
99
<description>Faster than Any Binary?</description>
1010
<releaseNotes>
11-
- Add support for detecting invalid json such as missing quotes
11+
- Eliminate need to check default value for property/field when SkipDefaultValue is set to false
1212
</releaseNotes>
1313
<language>en-US</language>
1414
<licenseUrl>https://github.com/rpgmaker/NetJSON/blob/master/LICENSE.text</licenseUrl>

NetJSON/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
// You can specify all the values or you can default the Build and Revision Numbers
3434
// by using the '*' as shown below:
3535
// [assembly: AssemblyVersion("1.0.*")]
36-
[assembly: AssemblyVersion("1.3.4")]
37-
[assembly: AssemblyFileVersion("1.3.4")]
36+
[assembly: AssemblyVersion("1.3.5")]
37+
[assembly: AssemblyFileVersion("1.3.5")]
3838
#if !NET_35 && !NET_STANDARD
3939
[assembly: SecurityRules(SecurityRuleSet.Level2, SkipVerificationInFullTrust = true)]
4040
#endif

NetJSON/lib/net35/NetJSON.dll

512 Bytes
Binary file not shown.

NetJSON/lib/net40/NetJSON.dll

512 Bytes
Binary file not shown.

NetJSON/lib/net462/NetJSON.dll

0 Bytes
Binary file not shown.

NetJSON/lib/net472/NetJSON.dll

0 Bytes
Binary file not shown.
512 Bytes
Binary file not shown.
512 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)