I'm developing a library with C#, .NET Framework 4.0 and Newtonsoft.Json 6.0.8.
I'm trying to create my own serializer:
public static string Serialize(List<Models.Codes> codes)
{
if (codes == null)
throw new ArgumentNullException("codes");
if (codes.Count == 0)
throw new ArgumentOutOfRangeException("codes");
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteStartArray();
foreach (Models.Codes code in codes)
writer.WriteValue(CodesSerializer.Serialize(code));
writer.WriteEndArray();
return sw.ToString();
}
public static string Serialize(Models.Codes code)
{
if (code == null)
throw new ArgumentNullException("code");
StringWriter sw = new StringWriter();
JsonTextWriter writer = new JsonTextWriter(sw);
writer.WriteStartObject();
writer.WritePropertyName("Code");
writer.WriteValue(code.Code);
writer.WritePropertyName("BatchId");
writer.WriteValue(code.BatchId);
writer.WritePropertyName("ProductId");
writer.WriteValue(code.ProductId);
writer.WritePropertyName("CodeLevel");
writer.WriteValue(code.CodeLevel);
writer.WritePropertyName("CommisioningFlag");
writer.WriteValue(code.CommisioningFlag);
writer.WritePropertyName("Timespan");
writer.WriteValue(code.Timespan);
if (!string.IsNullOrWhiteSpace(code.Username))
{
writer.WritePropertyName("Username");
writer.WriteValue(code.Username);
}
if (!string.IsNullOrWhiteSpace(code.Source))
{
writer.WritePropertyName("Source");
writer.WriteValue(code.Source);
}
if (!string.IsNullOrWhiteSpace(code.Reason))
{
writer.WritePropertyName("Reason");
writer.WriteValue(code.Reason);
}
writer.WriteEndObject();
string text = sw.ToString();
return text;
}
But it generates a string like this:
[\"{\\\"Code\\\":\\\"81861400008000002386\\\",\\\"BatchId\\\":5,\\\"ProductId\\\":7,\\\"CodeLevel\\\":1,\\\"CommisioningFlag\\\":1,\\\"Timespan\\\":null}\",
Have you notices the extra " before {?
How can I don't put that "?
I think the problem is that I am adding a value to an array inside the loop:
writer.WriteStartArray();
foreach (Models.Codes code in codes)
writer.WriteValue(CodesSerializer.Serialize(code));
writer.WriteEndArray();
I have changed writer.WriteValue(CodesSerializer.Serialize(code)); with writer.WriteRaw(CodesSerializer.Serialize(code)); and now it doesn't write ", but now I need to write JSON value delimiter and I can't use writer.WriteValueDelimiter();.
How can I add elements to a JSON array without adding "?
I have found the solution. I have to use writer.WriteRawValue():
writer.WriteStartArray();
foreach (Models.Codes code in codes)
writer.WriteRawValue(CodesSerializer.Serialize(code));
writer.WriteEndArray();
Related
So i have code that writes my data to a JSON with the library newtonsoft. But the problem now is that the JSON gets overwritten everytime instead of addes behind the previeous data.
Here is my code
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using (JsonWriter writer = new JsonTextWriter(sw))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartArray();
writer.WriteStartObject();
writer.WritePropertyName("Temperature");
writer.WriteValue(temperature);
writer.WritePropertyName("Score");
writer.WriteValue(score);
writer.WritePropertyName("TrackId");
writer.WriteValue(trackId);
/*
writer.WriteStartObject();
writer.WritePropertyName("CPU");
writer.WriteValue("Intel");
writer.WritePropertyName("PSU");
writer.WriteValue("500W");
writer.WritePropertyName("Drives");
writer.WriteStartArray();
writer.WriteValue("DVD read/writer");
writer.WriteComment("(broken)");
writer.WriteValue("500 gigabyte hard drive");
writer.WriteValue("200 gigabyte hard drive");
writer.WriteEnd();
*/
writer.WriteEndObject();
writer.WriteEnd();
}
System.IO.File.WriteAllText(#"C:/Users/Kimeru/Documents/Dermalog Noah WPF/data.json", sb.ToString());
This is the result I want to achieve:
[
{
"Temperature": "24.6",
"Score": "37",
"TrackId": 3
}
,
{
"Temperature": "16.8",
"Score": "38",
"TrackId": 4
}
]
I'm pretty new to the .NET coding world so I'm trying my best to explain.
I think a better solution would be to:
Read json and convert to list of class object that represents the json objects
Add, modify or remove objects from the list
Serialize the list of class objects to json
Write the new json to the file
I made a little example:
public class TrackData
{
public double Temperature { get; set; }
public double Score { get; set; }
public int TrackId { get; set; }
}
public void WriteJson(string filePath, List<TrackData> trackDataList)
{
string json = JsonConvert.SerializeObject(trackDataList);
using (StreamWriter sw = new StreamWriter(filePath))
{
sw.Write(json);
}
}
public List<TrackData> ReadJson(string filePath)
{
using (StreamReader sr = new StreamReader(filePath))
{
string json = sr.ReadToEnd();
return JsonConvert.DeserializeObject<List<TrackData>>(json);
}
}
Now you can use the methods and class this way:
List<TrackData> myTrackDataList = ReadJson("Filepath");
TrackData newTrackData = new TrackData();
newTrackData.Score = 38;
newTrackData.Temperature = 22;
newTrackData.TrackId = 5;
myTrackDataList.Add(newTrackData);
WriteJson("FilePath", myTrackDataList);
You use System.IO.File.WriteAllText(); which overrides the existing file.
Simply use System.IO.File.AppendAllText(); to add your text to the file.
I dont think its good idea to add to a json file like this,
save each object into a new json file so you can read it after.
Path.GetTempFileName() should give you a unique file name
System.IO.File.WriteAllText($#"C:/Users/Kimeru/Documents/Dermalog Noah WPF/{Path.GetTempFileName()}_data.json", sb.ToString());
There are other ways to get unique file name generated for you
How to Generate unique file names in C#
I wrote a simple class (.dll) in c#, which generates an html file.
I have to use a return in this class, I do not know how I can do it.
Code
public class Class1
{
private void HTMLGenerator()
{
string html = "<p>test</p>";
var xDocument = new XDocument(
new XDocumentType("html", null, null, null),
new XElement("html",
new XElement("head"),
new XElement("body",
XElement.Parse(html)
)
)
);
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Indent = true,
IndentChars = "\t"
};
using (var writer = XmlWriter.Create(#"C:\Users\\Desktop\test.html", settings))
{
xDocument.WriteTo(writer);
}
}
}
Html
<!DOCTYPE html >
<html>
<head></head>
<body><p>test</p></body>
</html>
Untested but this might help
public string HTMLGenerator()
{
// blah
using (var sw = new StringWriter())
{
using (var writer = XmlWriter.Create(sm, settings))
{
xDocument.WriteTo(writer);
}
return sw.ToString();
}
}
As noted in the comments
It is bad idea to construct HTML with XML writer (not as awful as
read, but still can produce undesired artefacts like extra new lines
at least)
I have a set codes, 0075, 0062 etc saved as a string in my database and declared as string in my model. However, when I am exporting my details in CSV using CSV Helper, the codes are not saved as text but as number. That is, 0075 saved as 75. I have tried adding "=" in front of the string, but this does not work. Or tried it as below. But in vain.
Below is my code:
streamWriter.WriteLine("Code;");
streamWriter.WriteLine(string.Join(";", "\""+result.Code+"\""));
Any idea how to saved result.Code which is declared as a string, as a text in my CSV?
Code as declared in the model:
public string Code { get; set; }
Looks like the method suggested by Formatting a comma-delimited CSV to force Excel to interpret value as a string works (on Excel 2010 at least), which is to format each cell as
"=""String Value"""
Here's a static helper class that does the necessary work. Since you used ; for a delimiter I reckon you are in a region where , is the decimal separator; to generalize my answer I'm using System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator as the list separator.
public static class CsvWriter
{
public static void WriteToCsv(IEnumerable<string> cells, TextWriter writer, CultureInfo cultureInfo = null)
{
if (cells == null || writer == null)
throw new ArgumentNullException();
string listSeparator = (cultureInfo ?? System.Globalization.CultureInfo.CurrentCulture).TextInfo.ListSeparator;
bool first = true;
foreach (var cell in cells)
{
if (!first)
writer.Write(listSeparator);
writer.Write(ToCsvCell(cell));
first = false;
}
writer.Write("\r\n");
}
public static void WriteToCsv<TEnumerable>(IEnumerable<TEnumerable> lines, TextWriter writer, CultureInfo cultureInfo = null) where TEnumerable : IEnumerable<string>
{
if (lines == null || writer == null)
throw new ArgumentNullException();
cultureInfo = cultureInfo ?? System.Globalization.CultureInfo.CurrentCulture;
foreach (var cells in lines)
WriteToCsv(cells, writer, cultureInfo);
}
public static string ToCsv<TEnumerable>(IEnumerable<TEnumerable> lines, CultureInfo cultureInfo = null) where TEnumerable : IEnumerable<string>
{
using (var writer = new StringWriter())
{
WriteToCsv(lines, writer, cultureInfo);
return writer.ToString();
}
}
static string ToCsvCell(string s)
{
if (s == null)
return "";
s = s.Replace("\"", "\"\"\"\"");
return string.Format("\"=\"\"{0}\"\"\"", s);
}
}
Then, to test:
var lines = new[]
{
new [] { "0075", "0062", "abc", DateTime.Today.ToShortDateString() },
new [] { "I said \"this is a quote\"" },
new [] { "Embedded new line: \r\nSecond Line", string.Concat(Enumerable.Repeat(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator, 5).ToArray()) },
};
var path = Path.Combine(Path.GetTempPath(), "TestQuestion34034950.csv");
using (var writer = new StreamWriter(path))
{
CsvWriter.WriteToCsv(lines, writer);
}
Console.WriteLine("Wrote " + path);
Excel will interpret all the CSV cells created by the above as string literals.
Using the bog-standard System.Xml.Serialization.XmlSerializer, I am serializing an object who's class inherits from another. Inspecting the resulting XML, the root node is being given the attributes "p1:type" and "xmlns:p1":
<ApiSubmission ApiVersion="1" CustId="100104" p1:type="OrderConfirmationApiSubmission"
xmlns:p1="http://www.w3.org/2001/XMLSchema-instance">
...
</ApiSubmission>
Is there a nice way to remove these attributes?
So I came upon this same issue ~5 years after this question was originally asked and was disappointed that no one had answered. After searching around I cobbled something together that allows me to strip out the type attribute in a derived class.
internal static string SerializeObject(object objectToSerialize, bool OmitXmlDeclaration = true, System.Type type = null, bool OmitType = false, bool RemoveAllNamespaces = true)
{
XmlSerializer x;
string output;
if (type != null)
{
x = new XmlSerializer(type);
}
else
{
x = new XmlSerializer(objectToSerialize.GetType());
}
XmlWriterSettings settings = new XmlWriterSettings() { Indent = false, OmitXmlDeclaration = OmitXmlDeclaration, NamespaceHandling = NamespaceHandling.OmitDuplicates };
using (StringWriter swriter = new StringWriter())
using (XmlWriter xmlwriter = XmlWriter.Create(swriter, settings))
{
x.Serialize(xmlwriter, objectToSerialize);
output = swriter.ToString();
}
if (RemoveAllNamespaces || OmitType)
{
XDocument doc = XDocument.Parse(output);
if (RemoveAllNamespaces)
{
foreach (var element in doc.Root.DescendantsAndSelf())
{
element.Name = element.Name.LocalName;
element.ReplaceAttributes(GetAttributesWithoutNamespace(element));
}
}
if (OmitType)
{
foreach (var node in doc.Descendants().Where(e => e.Attribute("type") != null))
{
node.Attribute("type").Remove();
}
}
output = doc.ToString();
}
return output;
}
I use this and [XmlInclude] the derived class in the base class. Then OmitType and RemoveAllNamespaces. Essentially the derived class is then treated as if it were the base class.
I use jsonconvert to convert simple objects to json like
JsonConvert.SerializeObject(new { label = "MyLabel1" });
to
{ "label":"MyLabel1" }
but i want to get the keys without quotation like
{ label: "MyLabel1"}
is there a way to convert objects to json withoud "key"-quotations by using jsonconvert?
Any library that expects JSON or actual JavaScript notation for creating objects (which is a superset of JSON) should work fine with quotes.
But if you really want to remove them, you can set JsonTextWriter.QuoteName to false. Doing this requires writing some code that JsonConvert.SerializeObject() uses by hand:
private static string SerializeWithoutQuote(object value)
{
var serializer = JsonSerializer.Create(null);
var stringWriter = new StringWriter();
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
jsonWriter.QuoteName = false;
serializer.Serialize(jsonWriter, value);
return stringWriter.ToString();
}
}
I complement answer #svick. For save format you need use StringBuilder for StringWriter.
static string SerializeWithoutQuote(object value)
{
var builder = new StringBuilder();
var serializer = JsonSerializer.Create();
var stringWriter = new StringWriter(builder);
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
jsonWriter.Formatting = Formatting.Indented;
jsonWriter.QuoteName = false;
serializer.Serialize(jsonWriter, value);
return builder.ToString();
}
}