Skip to content

Commit

Permalink
Fixed: some method calls did not accept IFormatProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
ronnygunawan committed Oct 10, 2019
1 parent 35824a6 commit 2eb71f2
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CsvSerializer/CsvSerializer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<RepositoryUrl>https://github.com/ronnygunawan/csv-serializer</RepositoryUrl>
<PackageTags>csv serializer deserializer parser core</PackageTags>
<Description>Fast CSV to object serializer and deserializer.</Description>
<Version>1.0.7</Version>
<Version>1.0.8</Version>
<PackageReleaseNotes></PackageReleaseNotes>
</PropertyGroup>

Expand Down
48 changes: 36 additions & 12 deletions CsvSerializer/Internal/NaiveImpl/NaiveDeserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,84 +182,108 @@ public List<object> Deserialize(IFormatProvider provider, char delimiter, bool s
for (int i = 0; i < _properties.Length; i++) {
switch (_deserializeAs[i]) {
case DeserializeAs.SByte:
if (sbyte.TryParse(columns[i].Span, out sbyte vSByte)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && sbyte.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out sbyte vSByte)) {
_properties[i].SetValue(item, vSByte);
} else if (sbyte.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vSByte)) {
_properties[i].SetValue(item, vSByte);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct sbyte format.");
}
break;
case DeserializeAs.Byte:
if (byte.TryParse(columns[i].Span, out byte vByte)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && byte.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out byte vByte)) {
_properties[i].SetValue(item, vByte);
} else if (byte.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vByte)) {
_properties[i].SetValue(item, vByte);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct byte format.");
}
break;
case DeserializeAs.Int16:
if (short.TryParse(columns[i].Span, out short vInt16)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && short.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out short vInt16)) {
_properties[i].SetValue(item, vInt16);
} else if (short.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vInt16)) {
_properties[i].SetValue(item, vInt16);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct Int16 format.");
}
break;
case DeserializeAs.UInt16:
if (ushort.TryParse(columns[i].Span, out ushort vUInt16)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && ushort.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out ushort vUInt16)) {
_properties[i].SetValue(item, vUInt16);
} else if (ushort.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vUInt16)) {
_properties[i].SetValue(item, vUInt16);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct UInt16 format.");
}
break;
case DeserializeAs.Int32:
if (int.TryParse(columns[i].Span, out int vInt32)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && int.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out int vInt32)) {
_properties[i].SetValue(item, vInt32);
} else if (int.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vInt32)) {
_properties[i].SetValue(item, vInt32);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct Int32 format.");
}
break;
case DeserializeAs.UInt32:
if (uint.TryParse(columns[i].Span, out uint vUInt32)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && uint.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out uint vUInt32)) {
_properties[i].SetValue(item, vUInt32);
} else if (uint.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vUInt32)) {
_properties[i].SetValue(item, vUInt32);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct UInt32 format.");
}
break;
case DeserializeAs.Int64:
if (long.TryParse(columns[i].Span, out long vInt64)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && long.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out long vInt64)) {
_properties[i].SetValue(item, vInt64);
} else if (long.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vInt64)) {
_properties[i].SetValue(item, vInt64);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct Int64 format.");
}
break;
case DeserializeAs.UInt64:
if (ulong.TryParse(columns[i].Span, out ulong vUInt64)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && ulong.TryParse(columns[i].Span[1..^1], NumberStyles.Integer, provider, out ulong vUInt64)) {
_properties[i].SetValue(item, vUInt64);
} else if (ulong.TryParse(columns[i].Span, NumberStyles.Integer, provider, out vUInt64)) {
_properties[i].SetValue(item, vUInt64);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct UInt64 format.");
}
break;
case DeserializeAs.Single:
if (float.TryParse(columns[i].Span, out float vSingle)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && float.TryParse(columns[i].Span[1..^1], NumberStyles.Float, provider, out float vSingle)) {
_properties[i].SetValue(item, vSingle);
} else if (float.TryParse(columns[i].Span, NumberStyles.Float, provider, out vSingle)) {
_properties[i].SetValue(item, vSingle);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct floating point format.");
}
break;
case DeserializeAs.Double:
if (double.TryParse(columns[i].Span, out double vDouble)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && double.TryParse(columns[i].Span[1..^1], NumberStyles.Float, provider, out double vDouble)) {
_properties[i].SetValue(item, vDouble);
} else if (double.TryParse(columns[i].Span, NumberStyles.Float, provider, out vDouble)) {
_properties[i].SetValue(item, vDouble);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct floating point format.");
}
break;
case DeserializeAs.Decimal:
if (decimal.TryParse(columns[i].Span, out decimal vDecimal)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && decimal.TryParse(columns[i].Span[1..^1], NumberStyles.Number, provider, out decimal vDecimal)) {
_properties[i].SetValue(item, vDecimal);
} else if (decimal.TryParse(columns[i].Span, NumberStyles.Number, provider, out vDecimal)) {
_properties[i].SetValue(item, vDecimal);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct decimal format.");
}
break;
case DeserializeAs.Boolean:
if (bool.TryParse(columns[i].Span, out bool vBoolean)) {
if (columns[i].Length >= 2 && columns[i].Span[0] == '"' && bool.TryParse(columns[i].Span[1..^1], out bool vBoolean)) {
_properties[i].SetValue(item, vBoolean);
} else if (bool.TryParse(columns[i].Span, out vBoolean)) {
_properties[i].SetValue(item, vBoolean);
} else if (!_isNullable[i] || columns[i].Length > 0) {
throw new CsvFormatException(typeof(T), _properties[i].Name, columns[i].ToString(), "Input string was not in correct Boolean format.");
Expand Down
12 changes: 9 additions & 3 deletions CsvSerializer/Internal/NaiveImpl/NaiveSerializer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Globalization;
using System.Reflection;
using System.Text;

Expand Down Expand Up @@ -93,7 +94,12 @@ public void SerializeItem(IFormatProvider provider, char delimiter, StringBuilde
}
switch (_serializeAs[i]) {
case SerializeAs.Number:
stringBuilder.AppendFormat("{0}", _properties[i].GetValue(item));
string? str = Convert.ToString(_properties[i].GetValue(item), provider);
if (str is string && str.Contains(delimiter)) {
stringBuilder.AppendFormat("\"{0}\"", str);
} else {
stringBuilder.AppendFormat("{0}", str);
}
break;
case SerializeAs.String:
if (((string?)_properties[i].GetValue(item))?.Replace("\"", "\"\"") is string stringValue) {
Expand All @@ -106,9 +112,9 @@ public void SerializeItem(IFormatProvider provider, char delimiter, StringBuilde
if (((DateTime?)_properties[i].GetValue(item)) is DateTime dateTimeValue) {
stringBuilder.Append('"');
if (_columnAttributes[i]?.DateFormat is string dateFormat) {
stringBuilder.Append(dateTimeValue.ToString(dateFormat));
stringBuilder.Append(dateTimeValue.ToString(dateFormat, provider));
} else {
stringBuilder.Append(dateTimeValue.ToString());
stringBuilder.Append(dateTimeValue.ToString(provider));
}
stringBuilder.Append('"');
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/DynamicSerializerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public void NullValuesAreSerializedToEmptyColumn() {
DateTime = new DateTime(2019, 8, 23)
};
csv = CsvSerializer.Serialize(new[] { obj }, withHeaders: true);
csv.Should().Be("\"Bool\",\"Byte\",\"SByte\",\"Short\",\"UShort\",\"Int\",\"UInt\",\"Long\",\"ULong\",\"Float\",\"Double\",\"Decimal\",\"String\",\"DateTime\"\r\nTrue,102,-100,-200,200,-3000,3000,-40000,40000,1E+14,1.7837193718273812E+19,989898989898,\"CSV Serializer\",8/23/2019 12:00:00 AM");
csv.Should().Be("\"Bool\",\"Byte\",\"SByte\",\"Short\",\"UShort\",\"Int\",\"UInt\",\"Long\",\"ULong\",\"Float\",\"Double\",\"Decimal\",\"String\",\"DateTime\"\r\nTrue,102,-100,-200,200,-3000,3000,-40000,40000,1E+14,1.7837193718273812E+19,989898989898,\"CSV Serializer\",\"8/23/2019 12:00:00 AM\"");
}

[Fact]
Expand Down
26 changes: 26 additions & 0 deletions Tests/InternationalizationTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using Csv;
using FluentAssertions;
using System;
using System.Collections.Generic;
using System.Globalization;
using Xunit;

namespace Tests {
public class InternationalizationTests {
private class MapCoordinates {
public double Latitude { get; set; }
public double Longitude { get; set; }
}

[Fact]
public void CanSerializeAndDeserializeInEN_USLocale() {
IFormatProvider provider = CultureInfo.GetCultureInfo("en-US");
Expand Down Expand Up @@ -36,6 +42,26 @@ public void CanSerializeAndDeserializeInEN_GBLocale() {
model.Double.Should().Be(123_456.789);
}

[Fact]
public void CanSerializeAndDeserializeWithModifiedThreadCulture() {
CultureInfo temp = CultureInfo.CurrentCulture;
try {
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("id-ID");
DecimalAndDouble model = new DecimalAndDouble {
Decimal = 123_456.789m,
Double = 123_456.789
};
string csv = CsvSerializer.Serialize(new[] { model });
DecimalAndDouble[] deserialized = CsvSerializer.Deserialize<DecimalAndDouble>(csv);
deserialized.Length.Should().Be(1);
model = deserialized[0];
model.Decimal.Should().Be(123_456.789m);
model.Double.Should().Be(123_456.789);
} finally {
CultureInfo.CurrentCulture = temp;
}
}

[Fact]
public void CanSerializeAndDeserializeInID_IDLocale() {
IFormatProvider provider = CultureInfo.GetCultureInfo("id-ID");
Expand Down
5 changes: 3 additions & 2 deletions Tests/SerializerTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Csv;
using FluentAssertions;
using System;
using System.Globalization;
using System.Linq;
using System.Net;
using Xunit;
Expand Down Expand Up @@ -52,7 +53,7 @@ public void PublicTypesAreSerializedUsingDynamicSerializer() {
StatusCode = HttpStatusCode.OK
};
string csv = CsvSerializer.Serialize(new[] { item }, withHeaders: true);
csv.Should().Be("\"Bool\",\"Byte\",\"SByte\",\"Short\",\"UShort\",\"Int\",\"UInt\",\"Long\",\"ULong\",\"Float\",\"Double\",\"Decimal\",\"String\",\"DateTime\",\"Uri\",\"StatusCode\"\r\nTrue,102,-100,-200,200,-3000,3000,-40000,40000,1E+14,1.7837193718273812E+19,989898989898,\"CSV Serializer\",8/23/2019 12:00:00 AM,\"http://localhost:5000/\",OK");
csv.Should().Be("\"Bool\",\"Byte\",\"SByte\",\"Short\",\"UShort\",\"Int\",\"UInt\",\"Long\",\"ULong\",\"Float\",\"Double\",\"Decimal\",\"String\",\"DateTime\",\"Uri\",\"StatusCode\"\r\nTrue,102,-100,-200,200,-3000,3000,-40000,40000,1E+14,1.7837193718273812E+19,989898989898,\"CSV Serializer\",\"8/23/2019 12:00:00 AM\",\"http://localhost:5000/\",OK");
}

[Fact]
Expand Down Expand Up @@ -182,7 +183,7 @@ public void CanDeserializeCsvFromExcel() {
string csv = @"No;Name;Price;Weight;CreatedDate;IsSuspended
10;Deflector, Dust (For Rear Differential);200000;20,5;13/12/2019;FALSE
13;""Deflector; Tire; Filter"";150000;15,5;20/11/2019;TRUE";
ExcelModel[] models = CsvSerializer.Deserialize<ExcelModel>(csv, hasHeaders: true, delimiter: ';');
ExcelModel[] models = CsvSerializer.Deserialize<ExcelModel>(csv, hasHeaders: true, delimiter: ';', provider: CultureInfo.GetCultureInfo("id-ID"));
models.Count().Should().Be(2);
}
}
Expand Down

0 comments on commit 2eb71f2

Please sign in to comment.