Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit e9ad33a

Browse files
committed
Added support for DataMember(EmitDefaultValue)
1 parent f62cf88 commit e9ad33a

File tree

4 files changed

+64
-33
lines changed

4 files changed

+64
-33
lines changed

src/ServiceStack.Text/Common/WriteType.cs

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ private static bool Init()
125125
var propertyInfo = propertyInfos[i];
126126

127127
string propertyName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyReflectedName;
128-
int propertyOrder = 0;
128+
int propertyOrder = -1;
129+
var propertyType = propertyInfo.PropertyType;
130+
bool suppressDefaultValue = !propertyType.IsValueType() || JsConfig.HasSerializeFn.Contains(propertyType);
131+
bool suppressNullValue = propertyType.GetDefaultValue() == null;
129132

130133
if (isDataContract)
131134
{
@@ -137,6 +140,8 @@ private static bool Init()
137140
propertyNameLowercaseUnderscore = dcsDataMember.Name ?? propertyName.ToLowercaseUnderscore();
138141
propertyReflectedName = dcsDataMember.Name ?? propertyInfo.ReflectedType.Name;
139142
propertyOrder = dcsDataMember.Order;
143+
suppressDefaultValue = !dcsDataMember.EmitDefaultValue;
144+
suppressNullValue &= !dcsDataMember.EmitDefaultValue;
140145
}
141146
else
142147
{
@@ -146,10 +151,6 @@ private static bool Init()
146151
propertyReflectedName = propertyInfo.ReflectedType.Name;
147152
}
148153

149-
var propertyType = propertyInfo.PropertyType;
150-
var suppressDefaultValue = propertyType.IsValueType() && JsConfig.HasSerializeFn.Contains(propertyType)
151-
? propertyType.GetDefaultValue()
152-
: null;
153154

154155
PropertyWriters[i] = new TypePropertyWriter
155156
(
@@ -158,9 +159,11 @@ private static bool Init()
158159
propertyNameCLSFriendly,
159160
propertyNameLowercaseUnderscore,
160161
propertyOrder,
162+
suppressDefaultValue,
163+
suppressNullValue,
161164
propertyInfo.GetValueGetter<T>(),
162165
Serializer.GetWriteFn(propertyType),
163-
suppressDefaultValue
166+
propertyType.GetDefaultValue()
164167
);
165168
}
166169

@@ -169,12 +172,10 @@ private static bool Init()
169172
var fieldInfo = fieldInfos[i];
170173

171174
string propertyName, propertyNameCLSFriendly, propertyNameLowercaseUnderscore, propertyReflectedName;
172-
int propertyOrder = 0;
173-
175+
int propertyOrder = -1;
174176
var propertyType = fieldInfo.FieldType;
175-
var suppressDefaultValue = propertyType.IsValueType() && JsConfig.HasSerializeFn.Contains(propertyType)
176-
? propertyType.GetDefaultValue()
177-
: null;
177+
bool suppressDefaultValue = !propertyType.IsValueType() || JsConfig.HasSerializeFn.Contains(propertyType);
178+
bool suppressNullValue = propertyType.GetDefaultValue()==null;
178179

179180
if (isDataContract)
180181
{
@@ -186,6 +187,8 @@ private static bool Init()
186187
propertyNameLowercaseUnderscore = dcsDataMember.Name ?? propertyName.ToLowercaseUnderscore();
187188
propertyReflectedName = dcsDataMember.Name ?? fieldInfo.ReflectedType.Name;
188189
propertyOrder = dcsDataMember.Order;
190+
suppressDefaultValue = !dcsDataMember.EmitDefaultValue;
191+
suppressNullValue &= !dcsDataMember.EmitDefaultValue;
189192
}
190193
else
191194
{
@@ -195,24 +198,21 @@ private static bool Init()
195198
propertyReflectedName = fieldInfo.ReflectedType.Name;
196199
}
197200

198-
199-
200201
PropertyWriters[i + propertyNamesLength] = new TypePropertyWriter
201202
(
202203
propertyName,
203204
propertyReflectedName,
204205
propertyNameCLSFriendly,
205206
propertyNameLowercaseUnderscore,
206207
propertyOrder,
208+
suppressDefaultValue,
209+
suppressNullValue,
207210
fieldInfo.GetValueGetter<T>(),
208211
Serializer.GetWriteFn(propertyType),
209-
suppressDefaultValue
212+
propertyType.GetDefaultValue()
210213
);
211214
}
212-
213-
214-
PropertyWriters = PropertyWriters.OrderBy(x => x.propertyOrder).ToArray();
215-
215+
PropertyWriters = PropertyWriters.OrderBy(x => x.propertyOrder).ToArray();
216216
return true;
217217
}
218218

@@ -231,6 +231,8 @@ internal string PropertyName
231231
}
232232
internal readonly string propertyName;
233233
internal readonly int propertyOrder;
234+
internal readonly bool propertySuppressDefaultValue;
235+
internal readonly bool propertySuppressNullValue;
234236
internal readonly string propertyReflectedName;
235237
internal readonly string propertyCombinedNameUpper;
236238
internal readonly string propertyNameCLSFriendly;
@@ -239,11 +241,13 @@ internal string PropertyName
239241
internal readonly WriteObjectDelegate WriteFn;
240242
internal readonly object DefaultValue;
241243

242-
public TypePropertyWriter(string propertyName, string propertyReflectedName, string propertyNameCLSFriendly, string propertyNameLowercaseUnderscore, int propertyOrder,
244+
public TypePropertyWriter(string propertyName, string propertyReflectedName, string propertyNameCLSFriendly, string propertyNameLowercaseUnderscore, int propertyOrder, bool propertySuppressDefaultValue,bool propertySuppressNullValue,
243245
Func<T, object> getterFn, WriteObjectDelegate writeFn, object defaultValue)
244246
{
245247
this.propertyName = propertyName;
246248
this.propertyOrder = propertyOrder;
249+
this.propertySuppressDefaultValue = propertySuppressDefaultValue;
250+
this.propertySuppressNullValue = propertySuppressNullValue;
247251
this.propertyReflectedName = propertyReflectedName;
248252
this.propertyCombinedNameUpper = propertyReflectedName.ToUpper() + "." + propertyName.ToUpper();
249253
this.propertyNameCLSFriendly = propertyNameCLSFriendly;
@@ -320,10 +324,21 @@ public static void WriteProperties(TextWriter writer, object value)
320324
var propertyValue = value != null
321325
? propertyWriter.GetterFn((T)value)
322326
: null;
323-
324-
if ((propertyValue == null
325-
|| (propertyWriter.DefaultValue != null && propertyWriter.DefaultValue.Equals(propertyValue)))
326-
&& !Serializer.IncludeNullValues) continue;
327+
328+
if (propertyValue == null)
329+
{
330+
if (propertyWriter.propertySuppressNullValue && !Serializer.IncludeNullValues)
331+
{
332+
continue;
333+
}
334+
}
335+
else if (propertyValue.Equals(propertyWriter.DefaultValue))
336+
{
337+
if (propertyWriter.propertySuppressDefaultValue && !Serializer.IncludeNullValues)
338+
{
339+
continue;
340+
}
341+
}
327342

328343
if (exclude.Any() && exclude.Contains(propertyWriter.propertyCombinedNameUpper)) continue;
329344

tests/ServiceStack.Text.Tests/JsonTests/JsonDataContractCompatibilityTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,22 @@ public void Can_serialize_a_movie()
2828
Assert.That(ssJson, Is.EqualTo(wcfJson));
2929
}
3030

31+
[Test]
32+
public void Respects_EmitDefaultValue()
33+
{
34+
using (var x = JsConfig.BeginScope())
35+
{
36+
x.IncludeNullValues = false;
37+
38+
var jsonModel = new Movie { Genres = null };
39+
40+
var ssJson = JsonSerializer.SerializeToString(jsonModel);
41+
var wcfJson = BclJsonDataContractSerializer.Instance.Parse(jsonModel);
42+
43+
Assert.That(ssJson, Is.EqualTo(wcfJson));
44+
}
45+
}
46+
3147
[Test]
3248
public void Can_deserialize_empty_type()
3349
{

tests/ServiceStack.Text.Tests/Support/DdnDtos.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -448,17 +448,17 @@ public ResponseStatus()
448448
this.Errors = new List<ResponseError>();
449449
}
450450

451-
[DataMember]
451+
[DataMember(EmitDefaultValue = false, IsRequired = false)]
452452
public string ErrorCode { get; set; }
453453

454-
[DataMember]
455-
public string Message { get; set; }
454+
[DataMember(EmitDefaultValue = false, IsRequired = false)]
455+
public string Message { get; set; }
456456

457-
[DataMember]
458-
public string StackTrace { get; set; }
457+
[DataMember(EmitDefaultValue = false, IsRequired = false)]
458+
public string StackTrace { get; set; }
459459

460-
[DataMember]
461-
public List<ResponseError> Errors { get; set; }
460+
[DataMember(EmitDefaultValue = false, IsRequired = false)]
461+
public List<ResponseError> Errors { get; set; }
462462

463463

464464
public bool IsSuccess

tests/ServiceStack.Text.Tests/Support/MovieDtos.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public Movie()
2727
this.Genres = new List<string>();
2828
}
2929

30-
[DataMember(Order = 1, EmitDefaultValue = false, IsRequired = false)]
30+
[DataMember(EmitDefaultValue = false, IsRequired = false)]
3131
[AutoIncrement]
3232
public int Id { get; set; }
3333

@@ -40,13 +40,13 @@ public Movie()
4040
[DataMember(Order = 4, EmitDefaultValue = false, IsRequired = false)]
4141
public decimal Rating { get; set; }
4242

43-
[DataMember(Order = 5, EmitDefaultValue = false, IsRequired = false)]
43+
[DataMember(Order = 5, EmitDefaultValue = true, IsRequired = false)]
4444
public string Director { get; set; }
4545

4646
[DataMember(Order = 6, EmitDefaultValue = false, IsRequired = false)]
4747
public DateTime ReleaseDate { get; set; }
4848

49-
[DataMember(Order = 7, EmitDefaultValue = false, IsRequired = false)]
49+
[DataMember(Order = 6, EmitDefaultValue = false, IsRequired = false)]
5050
public string TagLine { get; set; }
5151

5252
[DataMember(Order = 8, EmitDefaultValue = false, IsRequired = false)]

0 commit comments

Comments
 (0)