Skip to content

Commit

Permalink
Merge pull request #32 from FrendsPlatform/issue-31
Browse files Browse the repository at this point in the history
Added new parameter ForceQuotesAroundValues
  • Loading branch information
Svenskapojkarna authored Oct 9, 2023
2 parents 091f274 + ec8d38f commit 84864d5
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 68 deletions.
134 changes: 69 additions & 65 deletions Frends.Csv.Tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public void TestParseSkipRowsWithAutomaticHeaders()
dynamic resultJArray = result.ToJson();
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<year>2000</year>"));
Assert.AreEqual(resultJArray[0].price.ToString(), "2,34");
Assert.AreEqual("2,34", resultJArray[0].price.ToString());
}

[Test]
Expand All @@ -53,10 +53,10 @@ public void TestParseWithColumnSpecAndMissingHeader()
var resultJArray = result.ToJson() as JArray;
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<Year>2000</Year>"));
Assert.AreEqual(resultJArray[0]["Price"].Value<decimal>(), 2.34);
Assert.AreEqual(2.34, resultJArray[0]["Price"].Value<decimal>());
}

[Test]
Expand All @@ -75,10 +75,10 @@ public void TestParseWithNoColumnSpecAndNoHeader()
var resultJArray = result.ToJson() as JArray;
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<0>2000</0>"));
Assert.AreEqual(resultJArray[0]["3"].Value<string>(), "2,34");
Assert.AreEqual("2,34", resultJArray[0]["3"].Value<string>());
}

[Test]
Expand Down Expand Up @@ -106,37 +106,37 @@ public void TestParseWillAllKindOfDataTypes()
Csv = csv
}, new ParseOption() { ContainsHeaderRow = true, CultureInfo = "fi-FI", IgnoreReferences = true });
var resultJson = (JArray) result.ToJson();
Assert.AreEqual(resultJson[0]["Long"].Value<long>(), 4294967296);
Assert.AreEqual(4294967296, resultJson[0]["Long"].Value<long>());
var resultXml = result.ToXml();
Assert.IsTrue(resultXml.Contains("<DateTime2>1.5.2008 10.34.42</DateTime2>"));
var resultData = result.Data;
var itemArray = resultData[0];
Assert.AreEqual(itemArray[0].GetType(), typeof(int));
Assert.AreEqual(itemArray[0], 1997);
Assert.AreEqual(typeof(int), itemArray[0].GetType());
Assert.AreEqual(1997, itemArray[0]);

Assert.AreEqual(itemArray[1].GetType(), typeof(string));
Assert.AreEqual(itemArray[1], "Fo;rd");
Assert.AreEqual(typeof(string), itemArray[1].GetType());
Assert.AreEqual("Fo;rd", itemArray[1]);

Assert.AreEqual(itemArray[2].GetType(), typeof(decimal));
Assert.AreEqual(itemArray[2], 2.34d);
Assert.AreEqual(typeof(decimal), itemArray[2].GetType());
Assert.AreEqual(2.34d, itemArray[2]);

Assert.AreEqual(itemArray[3].GetType(), typeof(bool));
Assert.AreEqual(itemArray[3], true);
Assert.AreEqual(typeof(bool), itemArray[3].GetType());
Assert.AreEqual(true, itemArray[3]);

Assert.AreEqual(itemArray[4].GetType(), typeof(bool));
Assert.AreEqual(itemArray[4], true);
Assert.AreEqual(typeof(bool), itemArray[4].GetType());
Assert.AreEqual(true, itemArray[4]);

Assert.AreEqual(itemArray[5].GetType(), typeof(long));
Assert.AreEqual(itemArray[5], 4294967296);
Assert.AreEqual(typeof(long), itemArray[5].GetType());
Assert.AreEqual(4294967296, itemArray[5]);

Assert.AreEqual(itemArray[6].GetType(), typeof(char));
Assert.AreEqual(itemArray[6], 'f');
Assert.AreEqual(typeof(char), itemArray[6].GetType());
Assert.AreEqual('f', itemArray[6]);

Assert.AreEqual(itemArray[7].GetType(), typeof(DateTime));
Assert.AreEqual(itemArray[7], new DateTime(2008, 9, 15));
Assert.AreEqual(typeof(DateTime), itemArray[7].GetType());
Assert.AreEqual(new DateTime(2008, 9, 15), itemArray[7]);

Assert.That(itemArray[8].GetType(), Is.EqualTo(typeof(DateTime)));
Assert.That(itemArray[8], Is.EqualTo(new DateTime(2008, 5, 1, 10, 34, 42)));
Assert.AreEqual(typeof(DateTime), itemArray[8].GetType());
Assert.AreEqual(new DateTime(2008, 5, 1, 10, 34, 42), itemArray[8]);
}

[Test]
Expand All @@ -155,15 +155,15 @@ public void TestParseTreatMissingFieldsAsNullSetToTrue()
Csv = csv
}, new ParseOption() { ContainsHeaderRow = true, CultureInfo = "fi-FI", TreatMissingFieldsAsNulls = true });
var resultJson = (JArray)result.ToJson();
Assert.AreEqual(resultJson[2].Value<string>("header3"), null);
Assert.AreEqual(null, resultJson[2].Value<string>("header3"));

var resultXml = result.ToXml();
Assert.IsTrue(resultXml.Contains("<header3 />"));

var resultData = result.Data;
var nullItem = resultData[2][2];

Assert.AreEqual(nullItem, null);
Assert.AreEqual(null, nullItem);
}

[Test]
Expand Down Expand Up @@ -192,7 +192,7 @@ public void TestParseTreatMissingFieldsAsNullDefaultValue()
{
var options = new ParseOption();

Assert.AreEqual(options.TreatMissingFieldsAsNulls, false);
Assert.AreEqual(false, options.TreatMissingFieldsAsNulls);
}

[Test]
Expand All @@ -215,39 +215,50 @@ public void TestWriteFromListTable()
new List<object>() {100, "Dilantin", "Melanie", date}
};

var result = Csv.Create(new CreateInput() { InputType = CreateInputType.List, Delimiter = ";", Data = data, Headers = headers}, new CreateOption() { CultureInfo = "fi-FI" });
Assert.AreEqual(result.Csv,
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.List, Delimiter = ";", Data = data, Headers = headers}, new CreateOption() { CultureInfo = "fi-FI", ForceQuotesAroundValues = false });
Assert.AreEqual(
@"Dosage;Drug;Patient;Date
25;Indocin;David;1.1.2000 0.00.00
50;Enebrel;Sam;1.1.2000 0.00.00
10;Hydralazine;Christoff;1.1.2000 0.00.00
21;""Combiv;ent"";Janet;1.1.2000 0.00.00
100;Dilantin;Melanie;1.1.2000 0.00.00
");
", result.Csv);
}

[Test]
public void TestWriteFromJson()
{
var json = @"[{""cool"":""nice"", ""what"": ""no""}, {""cool"":""not"", ""what"": ""yes""}, {""cool"":""maybe"", ""what"": ""never""}]";
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json}, new CreateOption());
Assert.AreEqual(result.Csv,
Assert.AreEqual(
@"cool;what
nice;no
not;yes
maybe;never
");
", result.Csv);
}

[Test]
public void TestNullInputValue()
{
var json = @"[{""ShouldStayNull"":""null"", ""ShouldBeReplaced"": null}]";
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { ReplaceNullsWith = "replacedvalue" });
Assert.AreEqual(result.Csv,
Assert.AreEqual(
@"ShouldStayNull;ShouldBeReplaced
null;replacedvalue
");
", result.Csv);
}

[Test]
public void TestInputValueWithForceQuotes()
{
var json = @"[{""ShouldStayNull"":""null"", ""ShouldBeReplaced"": null}]";
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { ForceQuotesAroundValues = true });
Assert.AreEqual(
@"""ShouldStayNull"";""ShouldBeReplaced""
""null"";""""
", result.Csv);
}

[Test]
Expand All @@ -257,24 +268,17 @@ public void TestNoQuotesOption()
""foo"" : "" Normally I would have quotes "",
""bar"" : ""I would not""
}]";
var result2 = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { NeverAddQuotesAroundValues = false });
Assert.AreEqual(result2.Csv,
var result2 = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { ForceQuotesAroundValues = false, NeverAddQuotesAroundValues = false });
Assert.AreEqual(
@"foo;bar
"" Normally I would have quotes "";I would not
");
", result2.Csv);

var result1 = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { NeverAddQuotesAroundValues = true });
Assert.AreEqual(result1.Csv,
Assert.AreEqual(
@"foo;bar
Normally I would have quotes ;I would not
");







", result1.Csv);
}

[Test]
Expand All @@ -285,10 +289,10 @@ public void TestDatetimeValue()
""string"" : ""foo""
}]";
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { });
Assert.AreEqual(result.Csv,
Assert.AreEqual(
@"datetime;string
2018-11-22T10:30:55;foo
");
", result.Csv);
}

[Test]
Expand All @@ -300,10 +304,10 @@ public void TestDecimalValues()
""baz"" : 0.000000000000000000000000000000000000000000000000000000001
}]";
var result = Csv.Create(new CreateInput() { InputType = CreateInputType.Json, Delimiter = ";", Json = json }, new CreateOption() { });
Assert.AreEqual(result.Csv,
Assert.AreEqual(
@"foo;bar;baz
0.1;1.00;0.000000000000000000000000000000000000000000000000000000001
");
", result.Csv);
}

[Test]
Expand All @@ -328,10 +332,10 @@ public void ParseAndWriteShouldUseSeparateCultures()

var result = Csv.Create(new CreateInput() { InputType = CreateInputType.List, Delimiter = ";", Data = parseResult.Data, Headers = parseResult.Headers }, new CreateOption() { CultureInfo = "fi-FI" });

Assert.AreEqual(result.Csv,
Assert.AreEqual(
@"First;Second;Number;Date
Foo;"" bar"";100;1.1.2000 0.00.00
");
", result.Csv);
}

[Test]
Expand All @@ -351,10 +355,10 @@ public void TestParseRowsWithAutomaticHeadersWhiteSpaceRemovalDefault()
dynamic resultJArray = result.ToJson();
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<year of the z>"));
Assert.AreEqual(resultJArray[0].price.ToString(), "2,34");
Assert.AreEqual("2,34", resultJArray[0].price.ToString());
}

[Test]
Expand All @@ -374,10 +378,10 @@ public void TestParseRowsWithAutomaticHeadersWhiteSpaceRemovalGiven()
dynamic resultJArray = result.ToJson();
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<year_of_the_z>"));
Assert.AreEqual(resultJArray[0].price.ToString(), "2,34");
Assert.AreEqual("2,34", resultJArray[0].price.ToString());
}

[Test]
Expand All @@ -394,10 +398,10 @@ public void TestParseIgnoresQuotesInRowData()
dynamic resultJArray = result.ToJson();
var resultXml = result.ToXml();
var resultData = result.Data;
Assert.AreEqual(resultData.Count, 2);
Assert.AreEqual(resultJArray.Count, 2);
Assert.AreEqual(2, resultData.Count);
Assert.AreEqual(2, resultJArray.Count);
Assert.IsTrue(resultXml.Contains("<year>2000</year>"));
Assert.AreEqual(resultJArray[0].price.ToString(), "2,34");
Assert.AreEqual("2,34", resultJArray[0].price.ToString());
}

}
Expand Down
8 changes: 7 additions & 1 deletion Frends.Csv/Csv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,19 @@ public static CreateResult Create([PropertyTab] CreateInput input, [PropertyTab]
HasHeaderRecord = option.IncludeHeaderRow
};

if (option.ForceQuotesAroundValues)
{
config.ShouldQuote = (field) => true;
}

if (option.NeverAddQuotesAroundValues)
{
config.Mode = CsvMode.NoEscape;
// if IgnoreQuotes is true, seems like ShouldQuote function has to return false in all cases
// if IgnoreQuotes is false ShouldQuote can't have any implementation otherwise it will overwrite IgnoreQuotes statement ( might turn it on again)
config.ShouldQuote = (field) => (!option.NeverAddQuotesAroundValues);
config.ShouldQuote = (field) => false;
}

var csv = string.Empty;

switch (input.InputType)
Expand Down
11 changes: 10 additions & 1 deletion Frends.Csv/Definitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,19 @@ public class CreateOption
/// If set true csv's fields are never put in quotes
/// </summary>
[DefaultValue("false")]
public bool NeverAddQuotesAroundValues { get; set; }
public bool NeverAddQuotesAroundValues { get; set; } = false;

/// <summary>
/// Input's null values will be replaced with this value
/// </summary>
[DisplayFormat(DataFormatString = "Text")]
public string ReplaceNullsWith { get; set; }

/// <summary>
/// Force quotes to all values
/// </summary>
[DefaultValue("false")]
public bool ForceQuotesAroundValues { get; set; } = false;
}

public class CreateResult
Expand Down Expand Up @@ -163,6 +169,7 @@ public class ParseOption
/// </summary>
[DefaultValue("false")]
public bool TreatMissingFieldsAsNulls { get; set; } = false;

/// <summary>
/// A flag to let the reader know if reference should be ignored.
/// </summary>
Expand All @@ -175,6 +182,8 @@ public class ParseOption
[DefaultValue("false")]
public bool IgnoreQuotes { get; set; } = false;



}

public class ParseResult
Expand Down
2 changes: 1 addition & 1 deletion Frends.Csv/Frends.Csv.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<Version>1.0.1</Version>
<Version>1.0.0</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<Company>HiQ Finland</Company>
<Authors>HiQ Finland</Authors>
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ NOTE: Be sure to merge the latest from "upstream" before making a pull request!
| CultureInfo | string | The culture info to write the file with, e.g. for decimal separators. InvariantCulture will be used by default. See list of cultures [here](https://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx); use the Language Culture Name. <br> NOTE: Due to an issue with the CsvHelpers library, all CSV tasks will use the culture info setting of the first CSV task in the process; you cannot use different cultures for reading and parsing CSV files in the same process. |
| NeverAddQuotesAroundValues | bool | If set true csv's fields are never put in quotes |
| ReplaceNullsWith | string | Input's null values will be replaced with this value |
| ForceQuotesAroundValues | bool | Force quotes around all values |

#### Result

Expand Down

0 comments on commit 84864d5

Please sign in to comment.