I'm trying to deserialise a JSON file from local disk into an object. I've got the following, but this only seems to work when downloading it from the web:
var client = new HttpClient();
using (var s = await client.GetStreamAsync(filePath))
using (var sr = new StreamReader(s))
using (var jr = new JsonTextReader(sr))
{
var js = new JsonSerializer();
return js.Deserialize<MyObject>(jr);
}
I'm trying to find a way to do this, without first reading it into a string.
From Here
you can deserialize an object from file in two way.
Solution-1: Read file into a string and deserialize JSON to a type
string json = File.ReadAllText(#"c:\myObj.json");
MyObject myObj = JsonConvert.DeserializeObject<MyObject>(json);
Solution-2: Deserialize JSON directly from a file
using (StreamReader file = File.OpenText(#"c:\myObj.json"))
{
JsonSerializer serializer = new JsonSerializer();
MyObject myObj2 = (MyObject)serializer.Deserialize(file, typeof(MyObject));
}
You can download Newtonsoft.Json from NuGet by following command
Install-Package Newtonsoft.Json
using (var s = new StreamReader(filePath))
{
using (var jr = new JsonTextReader(s))
{
var js = new JsonSerializer();
var obj = js.Deserialize<MyObject>(jr);
return obj;
}
}
You might want to look at this : https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
It's an MSDN article called "How to: Serialize and Deserialize JSON Data"
Related
I have a string that contains a JSON. The only thing I know about this JSON is that it is valid. How to turn this string into BSON?
The BsonWriter of Newtonsoft.Json is obsolete.
You need to add a new nuget-package called Json.NET BSON (just search for newtonsoft.json.bson) and work with BsonDataWriter and BsonDataReader instead of BsonWriterand BsonReader:
public static string ToBson<T>(T value)
{
using (MemoryStream ms = new MemoryStream())
using (BsonDataWriter datawriter = new BsonDataWriter(ms))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(datawriter, value);
return Convert.ToBase64String(ms.ToArray());
}
}
public static T FromBson<T>(string base64data)
{
byte[] data = Convert.FromBase64String(base64data);
using (MemoryStream ms = new MemoryStream(data))
using (BsonDataReader reader = new BsonDataReader(ms))
{
JsonSerializer serializer = new JsonSerializer();
return serializer.Deserialize<T>(reader);
}
}
while using json in my project i noticed that there are simple and sweet way to convert json into a bson document.
string json = "{\"Name\":\"Movie Premiere\"}";
BsonDocument document = BsonDocument.Parse(json);
now you can use document as bson anywhere.
Note- I am using this document to insert into MongoDb database.
Hoping this will help you.
Behold! There is a much simpler way to do this:
BsonDocument doc = BsonDocument.Parse("{\"your\": \"json\", \"string\": \"here\"}");
I think this will do the trick for you
MongoDB.Bson.BsonDocument BSONDoc
= MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(json);
You can also have a look on Serialize to BSON and C# - Converting JSON string to BSON document
https://www.nuget.org/packages/Newtonsoft.Json
PM> Install-Package Newtonsoft.Json -Version 7.0.1
using Newtonsoft.Json.Bson;
using Newtonsoft.Json;
class Program
{
public class TestClass
{
public string Name { get; set; }
}
static void Main(string[] args)
{
string jsonString = "{\"Name\":\"Movie Premiere\"}";
var jsonObj = JsonConvert.DeserializeObject(jsonString);
MemoryStream ms = new MemoryStream();
using (BsonWriter writer = new BsonWriter(ms))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, jsonObj);
}
string data = Convert.ToBase64String(ms.ToArray());
Console.WriteLine(data);
}
}
Just another alternative, with the https://www.nuget.org/packages/MongoDB.Bson package, after using MongoDB.Bson;, you can just write byte[] result = someObj.ToBson();
See Deserializing from BsonDocument to string and serializing back to BsonDocument
Please note this is not a duplicate question as it is about parsing (and not deserializing) a large array object by object and retrieving the raw JSON.
I am dealing with very large arrays of JSON payload (tens of GB).
The structure of each object may be different i.e. heterogeneous:
[
{"id": "foo", "value": "bar"},
{"key": "foo", "name": "bar", "age": 10},
...
]
How can I go through the stream processing each object one at the time and retrieve the raw JSON string of each object?
My current solution is to use the StreamReader together with JsonTextReader to deserialize each object with a JObject and then retrieve the JSON using the .ToString(). But I prefer to avoid the performance cost and the GC allocation pressure of having to deserialize from JSON only to retrieve the JSON back again.
var file = new FileInfo(#"C:\Very.Large.Array.json");
using (var sr = new StreamReader(file.OpenRead()))
using (var reader = new JsonTextReader(sr))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
var obj = JObject.Load(reader);
var rawJSON = obj.ToString();
}
}
}
I believe you should use JsonTextWriter along with JsonTextReader. See below the simple POC class that demonstrates the idea.
I guess that some polishing is still required to bring this code to production quality. Like you may promote the StringBuilder sb from the local variable to the instance field and clear it at each iteration instead of creating new object.
But my goal was only to show the basic idea.
public class JsonBigFileReader
{
static string ReadSingleObject(JsonTextReader reader)
{
StringBuilder sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var writer = new JsonTextWriter(sw))
{
writer.WriteToken(reader, true); // writes current token including its children (meaning the whole object)
}
}
return sb.ToString();
}
public IEnumerable<string> ReadArray(string fileName)
{
var file = new FileInfo(fileName);
using (var sr = new StreamReader(file.OpenRead()))
using (var reader = new JsonTextReader(sr))
{
reader.Read();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
yield return ReadSingleObject(reader);
}
}
}
}
}
I am reading a NetworkStream for json string and then deserializing it using Newtonsoft.Json.
Sometimes, two json objects could be sent back-to-back and read at the same time on the stream. But the Newtonsoft.Json serializer gives me only one object.
For example, if I have the following string on the stream:
{"name":"John Doe","age":10}{"name":"Jane Doe","age":10}
If I deserialize the stream, the serializer reads the entire stream, but gives only the first object.
Is there a way to make the serializer read only the first object from the stream and then read the next object in the next iteration of a loop?
Code:
public static Person Deserialize(Stream stream)
{
var Serializer = new JsonSerializer();
var streamReader = new StreamReader(stream, new UTF8Encoding());
return Serializer.Deserialize<Person>(new JsonTextReader(streamReader));
}
I cannot deserialize as a list because I'm not receiving a json array.
I think you can do it like this:
public static IList<Person> Deserialize(Stream stream) {
var serializer = new JsonSerializer();
var streamReader = new StreamReader(stream, new UTF8Encoding());
var result = new List<Person>();
using (var reader = new JsonTextReader(streamReader)) {
reader.CloseInput = false;
// important part
reader.SupportMultipleContent = true;
while (reader.Read()) {
result.Add(serializer.Deserialize<Person>(reader));
}
}
return result;
}
Important part is SupportMultipleContent property, which notifies reader that there might be multiple json objects side to side.
you can try it doing like this
var httpRequest = HttpContext.Current.Request;
// This list will have all the stream objects
var persons = new List<Person>();
if (httpRequest.Files.Count > 0)
{
for (var obj = 0; doc < httpRequest.Files.Count; obj++)
{
var postedFile = httpRequest.Files[obj];
var bytes = new byte[postedFile.ContentLength];
postedFile.InputStream.Read(bytes, 0, postedFile.ContentLength);
persons.Add(Serializer.Deserialize<Person>(new JsonTextReader(new StreamReader(new MemoryStream(bytes)))));
}
}
how can I read the JSON from this site (http://www.pegelonline.wsv.de/webservices/rest-api/v2/stations.json?includeTimeseries=true&includeCurrentMeasurement=true) in C# with the Json.net library?
In this JSon there is only a array. I tested it with this code, but it doesn't work.
using (Stream stream = response.GetResponseStream())
{
JsonReader reader = new JsonTextReader(new StreamReader(stream));
dynamic info = JObject.Load(reader);
}
If i debug this, then VS says that the item is not an object. I try it with JArray.Load(reader); but then I don't know how to access the items.
You are right, JArray.Load is working correctly. The JArray then has a simple indexer to get to the individual items:
using (Stream stream = response.GetResponseStream())
{
var reader = new JsonTextReader(new StreamReader(stream));
var jsonArray = JArray.Load(reader);
var item20 = jsonArray[19];
var item20ShortName = (string)item20["shortname"];
}
I was given a XSD file and sample XML file, and asked to post the XML file to a URL.
Sample XML file
<?xml version="1.0"?>
<pingRequest>
<elt></elt>
...
</pingRequest>
I'm familiar with SOAP and REST, but I have never done posting pure XML file directly. Here is what I got so far.
1) Generate C# class from XSD file
xsd.exe Test.xsd /c
2) Serialize from C# class to XML using XmlSerializer
public string SerializeObject(object obj, Type type)
{
string xml;
var xs = new XmlSerializer(type);
using (var ms = new MemoryStream())
{
xs.Serialize(ms, obj, null);
ms.Position = 0;
using (var sr = new StreamReader(memoryStream))
{
xml = sr.ReadToEnd();
}
}
return xml;
}
OR Should I use LINQ to XML to generate XML file?
3) Post XML to URL using WebClient
var client = new WebClient();
var uri = new Uri("http://www.site.com/");
string responseXML = client.UploadString(uri, requestXML);
Am I at the right track? If not, could you please point me to a right direction? Thanks in advance.
Here is my partial code so that other can use it.
First, created two classes based on XML tags using xsd.exe Test.xsd /c (for both request and response), so that I do not have to prase the XML files manually.
public pingResponse Send()
{
var pingRequest = new pingRequest
{
myelement = "test"
};
// Serialize pingRequest class to xml
var serializer = new Serializer();
string requestXml = serializer.SerializeObject(pingRequest, typeof(pingRequest));
// Post xml
var client = new WebClient();
var uri = new Uri("http://www.site.com/");
string responseXML = client.UploadString(uri, requestXML);
return (pingResponse)serializer.DeserializeObject(xml, typeof(Response));
}
public class Serializer
{
public string SerializeObject(object obj, Type type)
{
var setting = new XmlWriterSettings() {OmitXmlDeclaration = true, Indent = true};
var xml = new StringBuilder();
using (var writer = XmlWriter.Create(xml, setting))
{
var nsSerializer = new XmlSerializerNamespaces();
nsSerializer.Add(string.Empty, string.Empty);
var xmlSerializer = new XmlSerializer(type);
xmlSerializer.Serialize(writer, obj, nsSerializer);
}
return xml.ToString();
}
public object DeserializeObject(string xml, Type type)
{
var xs = new XmlSerializer(type);
var stringReader = new StringReader(xml);
var obj = xs.Deserialize(stringReader);
stringReader.Close();
return obj;
}
}
Note: I do not include the PingRequest and PingResponse classes since my member variables will not be same as yours.