I am trying to convert a json string, containing array elements, to a .csv file. Below is the json string format:
{"inputFile": [["Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7", "Column8", "Column9", "Column10"], ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J"], ["K", "L", "M", "N", "O", "P", "Q", "R", "S", "T"]]}
solved. Thanks heyNow.
dynamic dynObj = JsonConvert.DeserializeObject(json);
var rowElements = new List<string>();
foreach (var data in dynObj.inputFile)
{
var row = new List<string>();
foreach (var dataItem in data)
{
var item = Convert.ToString(dataItem);
row.Add(item);
}
rowElements.Add( String.Join(",", row)+"\n");
}
var CSV = String.Join("",rowElements);
Console.WriteLine(CSV);
For RaJN:
Updated code to replace json file path to json string:
StringBuilder msg = new StringBuilder();
using (var p = ChoJSONReader.LoadText(jsonString)
.WithJSONPath("$.inputFile[*]")
)
{
using (var w = new ChoCSVWriter(msg))
{
w.Write(p);
}
Console.WriteLine(msg.ToString());
}
try with newtonsoft jsonparser.
If you can get your JSON as a string..
dynamic dynObj = JsonConvert.DeserializeObject(jsonString);
string CSV = "";
foreach (var data in dynObj.inputFile)
{
List<string> row = new List<string>();
foreach(var dataItem in data)
{
row.Add(dataItem);
}
CSV+=string.Join(row, ",");
}
You will get 1 giant string containing all the values as a CSV.
Let us know if this is what you want.
Here is how you can generate CSV from your JSON file using Cinchoo ETL
StringBuilder msg = new StringBuilder();
using (var p = new ChoJSONReader("*** YOUR JSON FILE PATH ***")
.WithJSONPath("$.inputFile[*]")
)
{
using (var w = new ChoCSVWriter(msg))
{
w.Write(p);
}
Console.WriteLine(msg.ToString());
}
Output:
Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8,Column9,Column10
A,B,C,D,E,F,G,H,I,J
K,L,M,N,O,P,Q,R,S,T
UPDATE:
string json = #"
{
""inputFile"": [
[""Column1"", ""Column2"", ""Column3"", ""Column4"", ""Column5"", ""Column6"", ""Column7"", ""Column8"", ""Column9"", ""Column10""],
[ ""A"", ""B"", ""C"", ""D"", ""E"", ""F"", ""G"", ""H"", ""I"", ""J"" ],
[ ""K"", ""L"", ""M"", ""N"", ""O"", ""P"", ""Q"", ""R"", ""S"", ""T"" ]
]
}";
StringBuilder msg = new StringBuilder();
using (var p = ChoJSONReader.LoadText(json)
.WithJSONPath("$.inputFile[*]")
)
{
using (var w = new ChoCSVWriter(msg))
{
w.Write(p);
}
Console.WriteLine(msg.ToString());
}
Related
I'm new to C# and I'm trying to create an object by looping over a string array:
indexKeys = ["A", "B", C"].
The elements of indexKeys are not known in advance.
I have an Object data, some of whose keys are present in indexKeys:
data = {"A": "string1", "B": "string2", "C": "string3", "D": "string4"}
The final object token must be a serialized form of:
{
"A": {
"S": "string1"
},
"B": {
"S": "string2"
},
"C": {
"S": "string3"
}
}
My code below is surely wrong but I'm confused about the data types in C#.
private string getToken(Object data, string[] indexKeys){
Token token = new Token{};
foreach(string i in indexKeys){
token.Add(i: {S: data[i]});
}
//return serialized token
}
How can I implement getToken to get the desired result?
You can use Dictionary like this:
var dataDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
var response = new Dictionary<string, object>();
foreach (var item in dataDictionary)
{
response.Add(item.Key, new { S = item.Value });
}
var json = JsonConvert.SerializeObject(response);
When data is object and using it directly(with reflection):
static string GetToken(object data, IEnumerable<string> indexKeys)
{
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = data.GetType().GetProperty(key).GetValue(data, null).ToString() });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var data = new { A = "string1", B = "string2", C = "string3", D = "string4" };
var result = GetToken(data, indexKeys);
Console.WriteLine(result);
}
If you supply data as dictionary instead of object:
static string GetToken(Dictionary<string, string> data, IEnumerable<string> indexKeys)
{
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = data[key] });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var dataDict = new Dictionary<string, string>()
{
{ "A", "string1" },
{ "B", "string2" },
{ "C", "string3" },
{ "D", "string4" }
};
var result = GetToken(dataDict, indexKeys);
Console.WriteLine(result);
}
When data is object but without using reflection:
static string GetToken(object data, IEnumerable<string> indexKeys)
{
var dataDict = JsonSerializer.Deserialize<Dictionary<string, object>>(JsonSerializer.Serialize(data));
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = dataDict[key] });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var data = new { A = "string1", B = "string2", C = "string3", D = "string4" };
var result = GetToken(data, indexKeys);
Console.WriteLine(result);
}
All of those solutions assume that your data object/dictionary will contain all the keys from indexKeys.
Hi im tring to convert CSV String to JSON, but the Header of the JSON has some issues with Encode i think.
Here the code and the Output:
[{...
"Endere_o_4": "",
"Endere_o_5": "",
"Endere_o_6": "",
"C_digo_Postal": "1000-045", ...]}
Expected Result: [{...
"Endereço_4": "",
"Endereço_5": "",
"Endereço_6": "",
"Código_Postal": "1000-045", ...]}
public void MssCSVtoJSON(string ssCSV, out string ssJSON)
{
ssJSON = "";
ChoCSVFileHeaderConfiguration headerConfiguration = new ChoCSVFileHeaderConfiguration(null, new System.Globalization.CultureInfo("pt-PT"));
ChoCSVRecordConfiguration config = new ChoCSVRecordConfiguration();
config.FileHeaderConfiguration = headerConfiguration;
StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(ssCSV,Encoding.Unicode, config, null).WithFirstLineHeader()) {
using (var w = new ChoJSONWriter(sb)) {
w.Configuration.Encoding = Encoding.Unicode;
w.Write(p);
}
}
ssJSON = sb.ToString();
// TODO: Write implementation for action
} // MssCSVtoJSON
It is known issue, put a fix and pushed ChoETL 1.1.0.5-alpha2 nuget package.
Here is working sample
string csv = #"Endereço_4, Endereço_5
1, 11
2, 22";
StringBuilder output = new StringBuilder();
using (var r = ChoCSVReader.LoadText(csv).WithFirstLineHeader())
{
using (var w = new ChoJSONWriter(output))
w.Write(r);
}
Console.WriteLine(output);
Output:
[
{
"Endereço_4": "1",
"Endereço_5": "11"
},
{
"Endereço_4": "2",
"Endereço_5": "22"
}
]
I am trying to parse a CSV file, with some lines commented out with the '#' character.
I am using the CsvHelper Configuration class to set the configuration for the CsvReader. However, it does not seems to register and still read my commented lines as input.
var config = new Configuration
{
Delimiter = ",",
Comment = '#',
Quote = '"',
HasHeaderRecord = false,
};
using (var stream = new StreamReader(filepath))
using (var reader = new CsvReader(stream, config))
{
while (reader.Read())
{
BsonDocument doc = new BsonDocument
{
{ "A", reader.GetField(0)},
{ "B", reader.GetField(1)},
{ "C", reader.GetField(2).ToLower()},
{ "D", reader.GetField(3)},
{ "E", Convert.ToBoolean(reader.GetField(4))},
{ "F", Convert.ToBoolean(reader.GetField(5))}
};
}
}
A sample of my data in my input.csv file:
#fieldA,fieldB,fieldC,fieldD,fieldE,fieldF
valueA,valueB,valueC,valueD,true,false
valueA,valueB,valueC,valueD,true,false
#valueA,valueB,valueC,valueD,true,false
valueA,valueB,valueC,valueD,true,false
Only the below works. Or you can don't explicitly state the comment char if it is the default '#'.
var config = new Configuration
{
Delimiter = ",",
//Comment = '#' //this does not work although # is the default
Comment = Convert.ToChar("#"),
Quote = '"',
HasHeaderRecord = false,
AllowComments = true,
};
I believe the AllowComments = true is the critical part. I was able to get it to work even when I set Comment = '#', but that isn't necessary since it is the default. I wonder if cultural settings could be playing a part.
var config = new Configuration
{
HasHeaderRecord = false,
AllowComments = true
};
using (var stream = new StreamReader(filepath))
using (var reader = new CsvReader(stream, config))
{
while (reader.Read())
{
BsonDocument doc = new BsonDocument
{
{ "A", reader.GetField(0)},
{ "B", reader.GetField(1)},
{ "C", reader.GetField(2).ToLower()},
{ "D", reader.GetField(3)},
{ "E", Convert.ToBoolean(reader.GetField(4))},
{ "F", Convert.ToBoolean(reader.GetField(5))}
};
}
}
There is a problem in CsvHelper when you try to prefix your csv file with comments while having HasHeaderRecord = true. The workaround is to put your csv header as the first line in the csv, then follow it by your comment block.
Since I believe this is a non-intuitive solution, I left an issue for the CsvHelper contributors to fix:
https://github.com/JoshClose/CsvHelper/issues/2039
I want to convert my csv file into .json format using c#. here what i have tried:
var lines = #"text,intentName,entityLabels
1,2,null
2,1,null".Replace("\r", "").Split('\n');
var csv = lines.Select(l => l.Split(',')).ToList();
var headers = csv[0];
var dicts = csv.Skip(1).Select(row => Enumerable.Zip(headers, row,
Tuple.Create).ToDictionary(p => p.Item1, p => p.Item2)).ToArray();
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(dicts);
Result1.Text = json;
The result is :
[
{
"text":" 1",
"intentName":"2",
"entityLabels":"null"
},
{
"text":"2",
"intentName":"1",
"entityLabels":"null"
}
]
it almost like I expected, however I want to make if the entityLabels column is null, then it replace into []. so the output that I expecting is:
[
{
"text":" 1",
"intentName":"2",
"entityLabels":[]
},
{
"text":"2",
"intentName":"1",
"entityLabels":[]
}
]
anyone know how to do it?
With external lib Cinchoo ETL - an open source library, you can convert CSV --> JSON with the expected format as below
Method 1:
string csv = #"text,intentName,entityLabels
1,2,null
2,1,null
";
StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(csv)
.WithFirstLineHeader()
.WithField("text")
.WithField("intentName")
.WithField("entityLabels", fieldType: typeof(int[]), nullValue: "null")
)
{
using (var w = new ChoJSONWriter(sb)
)
w.Write(p);
}
Console.WriteLine(sb.ToString());
Sample fiddle: https://dotnetfiddle.net/5M7fFX
Method 2:
string csv = #"text,intentName,entityLabels
1,2,null
2,1,null
";
StringBuilder sb = new StringBuilder();
using (var p = ChoCSVReader.LoadText(csv)
.WithFirstLineHeader()
.WithField("text")
.WithField("intentName")
.WithField("entityLabels", valueConverter: (o) => new int[] { })
)
{
using (var w = new ChoJSONWriter(sb)
)
w.Write(p);
}
Console.WriteLine(sb.ToString());
Sample fiddle: https://dotnetfiddle.net/gOX3FJ
Output:
[
{
"text": "1",
"intentName": "2",
"entityLabels": []
},
{
"text": "2",
"intentName": "1",
"entityLabels": []
}
]
Hope it helps.
Don't try to use string operations to convert from one data type to another.
Instead use an actual CSV parsing library like csvhelper (available on NuGet) to deserialise the CSV into objects, and then re-serialise that same data as JSON using a JSON serializer.
I have a json file in the following format:
{
"HDRDTL":["SRNO","STK_IDN","CERTIMG"],
"PKTDTL":[
{"SRNO":"2814","STK_IDN":"1001101259","CERTIMG":"6262941723"},
{"SRNO":"2815","STK_IDN":"1001101269","CERTIMG":"6262941726"},
{"SRNO":"2816","STK_IDN":"1001101279","CERTIMG":"6262941729"}
],
"IMGTTL":
["CERTIMG","ARRIMG"],
"IMGDTL":{"CERTIMG":"CRd6z2uq3gvx7kk","ARRIMG":"ASd6z2uq3gvx7kk"}
}
The "PKTDTL" array is the part I need to convert to csv.
How can I achieve this in C# ?
Note, as an example, I only have 3 items in the "PKTDTL", the real json file has thousands of lines of ({"SRNO" ...}) and is huge.
I have written following code which does not work. see error message commented in the code.
Question
Anyone knows why it failed ?
Do you have a better/alternative method
public static void ConvertJsonToCSV(string InFile)
{
string OutFile=InFile.Replace("json","csv");
StreamReader sInFile = new StreamReader(InFile);
StreamWriter sOutFile = new StreamWriter(OutFile);
using (sInFile)
{
string sJson = sInFile.ReadToEnd();
//*************************************************************
// the below line failed, error message: unexpected json token
// when reading datatable, expected startArray, got StartObject.
//**************************************************************
DataTable dt = JsonConvert.DeserializeObject<DataTable>(sJson);
//DataTable dt = JsonConvert.DeserializeAnonymousType(sJson, new { Makes = default(DataTable) }).Makes;
var sb = new StringBuilder();
string[] columnNames = (from dc in dt.Columns.Cast<DataColumn>()
select dc.ColumnName).ToArray();
sb.AppendLine(string.Join(",", columnNames));
foreach (DataRow dr in dt.Rows)
{
foreach (object field in dr.ItemArray)
{
sb.Append(field.ToString().Replace(",", "") + ",");
}
sb.Replace(",", "\n", sb.Length - 1, 1);
}
sOutFile.Write(sb.ToString());
sOutFile.Close();
sInFile.Close();
}
}
With Cinchoo ETL - an open source library, you can do do the conversion easily with few lines of code
string json = #"{
""HDRDTL"":[""SRNO"",""STK_IDN"",""CERTIMG""],
""PKTDTL"":[
{""SRNO"":""2814"",""STK_IDN"":""1001101259"",""CERTIMG"":""6262941723""},
{""SRNO"":""2815"",""STK_IDN"":""1001101269"",""CERTIMG"":""6262941726""},
{""SRNO"":""2816"",""STK_IDN"":""1001101279"",""CERTIMG"":""6262941729""}
],
""IMGTTL"":
[""CERTIMG"",""ARRIMG""],
""IMGDTL"":{""CERTIMG"":""CRd6z2uq3gvx7kk"",""ARRIMG"":""ASd6z2uq3gvx7kk""}
}";
StringBuilder sb = new StringBuilder();
using (var p = ChoJSONReader.LoadText(json).WithJSONPath("$..PKTDTL")
)
{
using (var w = new ChoCSVWriter(sb)
.WithFirstLineHeader()
)
w.Write(p);
}
Console.WriteLine(sb.ToString());
Output:
SRNO,STK_IDN,CERTIMG
2814,1001101259,6262941723
2815,1001101269,6262941726
2816,1001101279,6262941729
Checkout CodeProject article for some additional help.
Disclaimer: I'm the author of this library.
I found myself in similar situation. this is what i did. first I created a JObject (using Newtonsoft.Json.Linq) let us consider that your json is in a string variable called "strJSON".
JObject jsonObj= JObject.parse(strJSON);
JObject PKTDL=jsonObj["PKTDTL"] as JObject;
IList<string> keys = PKTDL.Properties().Select(p => p.Name).ToList(); // this gives column names
StringBuilder sb=new StringBuilder();
string headers="";
foreach(string key in keys)
{
headers+=","+key;
}
sb.AppendLine(headers.TrimStart(','));
foreach(JObject j in jsonObj["PKTDTL"]) //if jobject doesnt work try "JToken j"
{
string values="";
foreach(string key in keys)
{
values+=","+jsonObj["PKTDTL"][key];
}
sb.AppendLine(values.TrimStart(','));
}
File.WriteAllText(filePath, sb.ToString());
then save sb as a csv
Similar question to duplicate (see the JsonToCsv(string, string) method there). If you are already using NewtonSoft Json.NET and CsvHelper you can do similar conversion with the help of ExpandoObject.
var jsonText = #"{
""HDRDTL"":[""SRNO"",""STK_IDN"",""CERTIMG""],
""PKTDTL"":[
{""SRNO"":""2814"",""STK_IDN"":""1001101259"",""CERTIMG"":""6262941723""},
{""SRNO"":""2815"",""STK_IDN"":""1001101269"",""CERTIMG"":""6262941726""},
{""SRNO"":""2816"",""STK_IDN"":""1001101279"",""CERTIMG"":""6262941729""}
],
""IMGTTL"":
[""CERTIMG"",""ARRIMG""],
""IMGDTL"":{""CERTIMG"":""CRd6z2uq3gvx7kk"",""ARRIMG"":""ASd6z2uq3gvx7kk""}
}";
var jtoken = JObject.Parse(jsonText).SelectToken("$..PKTDTL");
var expandos = jtoken.ToObject<ExpandoObject[]>();
string csvText;
using (var writer = new StringWriter())
{
using (var csv = new CsvWriter(writer))
{
csv.WriteRecords(expandos as IEnumerable<dynamic>);
}
csvText = writer.ToString();
}
Console.WriteLine(csvText);