Invalid Operation Exception , No elements in the sequence - c#

private static void WriteJson(string filepath,
string filename,
JsonSchema jsonschema)
{
using (TextWriter writer = File.CreateText(
#"C:\Users\ashutosh\Desktop\Output\" + filename + ".js"))
using (var jtw = new JsonTextWriter(writer))
{
jtw.Formatting = Formatting.Indented;
jsonschema.WriteTo(jtw);
}
//var json = JsonConvert.SerializeObject(
// jsonschema, Formatting.Indented,
// new JsonSerializerSettings {
// NullValueHandling = NullValueHandling.Ignore });
// File.WriteAllText(
// #"C:\Users\ashutosh\Desktop\Output\" + filename + ".js", json);
}
I am creating a JSONSchema from JSON.net , and then writing it out . I get a
Invalid Operation Exception Sequence contains no matching element
But when I use the commented code instead of the usual stuff. No such exception appears.
1) What is causing this exception?
2) I would have used the second method happily but it doesn't feel intuitive and it will print out the integer value of the JsonType for schema.Type instead of the (array,integer,bool etc..)
What can I do to get out of this situation?
UPDATE
The exception happens when the "Properties" property of the JsonSchema has count = 0 .
Properties is Dictionary<String,JsonSchema>. I have initialise it so it is not null. Eventually the code may or may not add elements to it . so , the count may remain 0.

By default, enums will be serialized to theirs corresponding integer value. You can change that easily by supplying StringEnumConverter in your serializer settings:
var json = JsonConvert.SerializeObject(jsonschema, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
Converters = new List<JsonConverter> { new StringEnumConverter() }
});
Edit:
I run this simple test code:
var schema = new JsonSchemaGenerator().Generate(typeof(CustomType));
Debug.Assert(schema.Properties.Count == 0);
using (TextWriter textWriter = File.CreateText(#"schema.json"))
using (var jsonTextWriter = new JsonTextWriter(textWriter))
{
jsonTextWriter.Formatting = Formatting.Indented;
schema.WriteTo(jsonTextWriter);
}
// CustomType is a class without any fields/properties
public class CustomType { }
Code above serializes schema correctly to:
{
"type": "object",
"properties": {}
}
Is the schema you are generating correct? It seems as if serializer was "thinking" it should deal with some properties when there are actually none. Can you show type you generate schema from? There might be a problem with type which causes invalid schema to generate - but still, I cannot reproduce it.

Related

How to write a string property value to JsonTextWriter with a TextWriter?

I have C# class that can have content of various types, and an method that can write that content to a TextWriter in an efficient manner. In certain cases, I have a collection of these objects that I write out as JSON array. So, I have a JsonTextWriter which is set up appropriately. It's in a state where I have called the methods to create the container JObject, JArray and JObject. I've called JsonTextWriter.WritePropertyName() and now comes this instance method.
public void WriteContentToValue(JsonTextWriter writer)
{
if (this.Content is JToken) {
(this.Content as JToken).WriteTo(writer);
} else {
using (StringWriter swriter = new StringWriter()) {
WriteContentTo(swriter);
writer.WriteValue(swriter.ToString());
}
}
}
WriteContentTo(swriter) is a call to the method I mentioned earlier that takes a TextWriter. I'm looking for a alternative to the code in the else block that doesn't involve creating a StringWriter instance and forcing creation of an intermediary string with StringWriter.ToString() in order to call JsonTextWriter.WriteValue(string).
There is no deserialization happening in this that I can see.
JObject o = new JObject(
new JProperty("Name", "John Smith"),
new JProperty("BirthDate", new DateTime(1983, 3, 20))
);
JsonSerializer serializer = new JsonSerializer();
Person p = (Person)serializer.Deserialize(new JTokenReader(o), typeof(Person));
Console.WriteLine(p.Name);
When using StringWriter be sure to be careful of your instances.
I would highly recommend looking into the documentation on this as well. https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JTokenWriter.htm

Read as much JSON data from the stream as possible

Is there any way to read a JSON object from the stream where it's followed by other data, and thus the only way to find out that we should stop reading is by reaching the position where the object's opening brace is closed?
{
"SomeData": "blahblah",
"SubObject": {
"SomeData": "blahblah}{{"
}
}
... and some more text (not JSON)
I assume you're going to use Json.Net library. In this case it will cater for your particular use case out of the box.
consider the following:
var s = "{ \"SomeData\": \"blahblah\", \"SubObject\": {\"SomeData\": \"blahblah}{{\" } } sdfsdfsdf... and some more data";
var obj1 = JsonConvert.DeserializeObject(s, new JsonSerializerSettings() {
CheckAdditionalContent = false // this is the key here, otherwise you will get an exception
});
JsonSerializer serializer = new JsonSerializer();
var obj2 = serializer.Deserialize(new JsonTextReader(new StringReader(s))); // no issues here either

JsonDocument Get JSON String

I need an example of getting a JSON string from a JsonDocument. I can get properties with RootElement.GetProperty("ItemName") and then call .GetString() but can't see a way to just get the root element as a JSON string?
Here an example:
JsonDocument jdoc = JsonDocument.Parse("{\"a\":123}");
using(var stream = new MemoryStream())
{
Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
jdoc.WriteTo(writer);
writer.Flush();
string json = Encoding.UTF8.GetString(stream.ToArray());
}
For an easier usage you could put it in an extension method like:
public static string ToJsonString(this JsonDocument jdoc)
{
using (var stream = new MemoryStream())
{
Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
jdoc.WriteTo(writer);
writer.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
}
And use it like:
JsonDocument jdoc = JsonDocument.Parse("{\"a\":123}");
string json = jdoc.ToJsonString();
I have use RootElement to get a JsonElement and then call .ToString().
JsonDocument jdoc = JsonDocument.Parse("{\"a\":123}");
string json = jdoc.RootElement.ToString();
For the record there are 2 code snippets in official doco at How to serialize and deserialize (marshal and unmarshal) JSON in .NET
A. Use JsonDocument to write JSON
The following example shows how to write JSON from a JsonDocument:
(surprisingly long code snippet here)
The preceding code:
Reads a JSON file, loads the data into a JsonDocument, and writes formatted (pretty-printed) JSON to a file.
Uses JsonDocumentOptions to specify that comments in the input JSON are allowed but ignored.
When finished, calls Flush on the writer. An alternative is to let the writer autoflush when it's disposed.
B. Use Utf8JsonWriter
The following example shows how to use the Utf8JsonWriter class:
(...)
The snipped can be adjusted to use JsonDocument.Parse:
using var stream = new System.IO.MemoryStream();
using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))
{
var jsonDocument = JsonDocument.Parse(content);
jsonDocument.WriteTo(writer);
}
var formatted = System.Text.Encoding.UTF8.GetString(stream.ToArray());

Discarding garbage characters after json object with Json.Net

I have to consume a so called web service implemented by a dumb monkey which is returning some garbage after the proper Json response.
Something like this:
{
"Property1": 1,
"Property2": 2,
"Property3": 3
}<?xml version='1.0' ?>Maybe some other gibberish nonsense I wish to discard.
Now, I could just search for "<?xml" and split, but I was wondering if I can use a stream reader or something to read up to the closing } and then discard the rest.
I'm using C# and Json.Net.
You can also set JsonSerializerSettings.CheckAdditionalContent = false to tell the serializer to ignore any content after the end of the deserialized JSON object:
var result = JsonConvert.DeserializeObject<Dictionary<string, long>>(json, new JsonSerializerSettings { CheckAdditionalContent = false })
Oddly enough it is necessary to do this explicitly despite the fact that the default value seems to be false already, since the underlying field is nullable.
I knew there had to be a simple and robust way:
public T ReadTypeAndDiscardTheRest<T>(string json)
{
using (var sr = new StringReader(json))
using (var jsonReader = new JsonTextReader(sr))
{
var token = JToken.Load(jsonReader);
return token.ToObject<T>();
}
}
[Test]
public void TestJsonDiscarding()
{
var json = #"{""Key"":""a"", ""Value"":""n""}<?xml>aaaa";
var kp = ReadTypeAndDiscardTheRest<KeyValuePair<string, string>>(json);
Assert.That(kp.Key, Is.EqualTo("a"));
Assert.That(kp.Value, Is.EqualTo("n"));
}
As always, Json.Net FTW.

Deserialize DateTime? Json

I have a list which contains elements of class type which contains a property
[DataMember]
public DateTime? DateOfBirth { get; set; }
im serializing the whole list to a file like so:
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new JavaScriptDateTimeConverter());
serializer.NullValueHandling = NullValueHandling.Ignore;
using (StreamWriter sw = new StreamWriter(#"c:\json.txt"))
using (JsonWriter writer = new JsonTextWriter(sw))
{
serializer.Serialize(writer, _myList);
}
and when i try to deserialize like so:
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new JavaScriptDateTimeConverter());
string text = System.IO.File.ReadAllText(#"c:\json.txt");
_myList = JsonConvert.DeserializeObject<List<UserInformation>>(text);
I'm getting the following error:
Error setting value to 'DateOfBirth' on 'Namespace'.
EDIT -
Json Looks like: "DateOfBirth":new Date(-1459735200000) (i couldn't find how it looks when DateOfBirth == null)
I'm a beginner using Json, and im having difficulty understanding it as it is, can someone explain to me what is the problem and how do i fix this?
Thanks in advance
if you use the newtonsoft library, then you could add a nice little generic method to Deserializeyour json:
public T Deserialize<T>(string json)
{
try
{
var value = Newtonsoft.Json.JsonConvert
.DeserializeObject<T>(json);
return value;
}
catch (Exception ex)
{
// examine the ex.Message here if required
}
return default(T);
}
This may take you a step closer
Since I didn't get an answer that helped me, I'll post what solution I've used to solve this. I didn't really want to do this but I had to change DateTime to long, and save the Ticks instead, and when i need the date i can convert like so
DateTime dt = new DateTime(long ticks);

Categories