Unable to Deserialize Object using Newton Json - c#

I tried with following code but getting error for input parameter as string.
protected override object DeserializeCore(Type type, byte[] value)
{
using (var ms = new MemoryStream(value))
using (var sr = new StreamReader(ms, Encoding.UTF8))
{
var result = Newtonsoft.Json.JsonConvert.DeserializeObject(sr, type);
return result;
}
}
and I passed it as sr.ToString() getting error :
Unexpected character encountered while parsing value: S. Path '', line 0, position 0.

Would this not be simpler?
protected override object DeserializeCore(Type type, byte[] value) {
var str = System.Text.Encoding.UTF8.GetString(value);
return JsonConvert.DeserializeObject(str, type);
}
(I can't figure out why you are using the streams. Is it related to some issue with the encoding?)

try this -
public class JsonObject
{
public object Value { get; set; }
public string Type { get; set; }
}
var s = "{'Value':{'something':'test'},'Type':'JsonData'}";
var o = DeserializeCore(typeof(JsonObject), Encoding.UTF8.GetBytes(s.ToCharArray()));
should work fine.

Related

How to cast Newtonsoft.Json.Linq.JObject to complex type?

Given the following c# code:
using Newtonsoft.Json;
using System;
namespace ConsoleApp2
{
internal class Program
{
public class BatteryStatus
{
// The battery level reports percentage of the full battery.The field can take values from 0 to 100% (0x00 – 0x64).
// The value 0xFF indicates a battery low warning.
public byte BatteryLevel { get; set; }
public bool LowBatteryWarning { get; set; }
public DateTime TimestampUtc { get; set; }
public BatteryStatus(byte batteryLevel)
{
TimestampUtc = DateTime.UtcNow;
if (batteryLevel == 0xff)
{
LowBatteryWarning = true;
batteryLevel = 0;
}
BatteryLevel = batteryLevel;
}
}
static void Main(string[] args)
{
BatteryStatus batteryStatus = new BatteryStatus(40);
string json = SaveObjectToJsonString(batteryStatus);
Object obj = ReadObjectFromJsonString(json);
}
static string SaveObjectToJsonString(Object obj)
{
string json = JsonConvert.SerializeObject(obj);
return json;
}
static Object ReadObjectFromJsonString(string json)
{
var obj = JsonConvert.DeserializeObject(json);
return obj;
}
}
}
Without changing the SaveObjectToString or ReadObjectFromString functions (and pretend that you didn't even see the source code for these), how can obj be converted to an object of the BatteryStatus class?
Attempting to cast directly like this:
batteryStatus = (BatteryStatus)obj;
result in the following error:
Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'BatteryStatus'.
You can use JObject.ToObject method.
static void Main(string[] args)
{
BatteryStatus batteryStatus = new BatteryStatus(40);
string json = SaveObjectToJsonString(batteryStatus);
var obj = ReadObjectFromJsonString(json);
JObject jObj = obj is JObject ? (JObject)obj : JObject.FromObject(obj);
var deserializedBatteryStatus = jObj.ToObject<BatteryStatus>();
}
Would something using generics work for your use case?
We could change your ReadObjectFromJsonString and SaveObjectToJsonString to use generics...
static string SaveObjectToJsonString<T>(Object obj) where T: class
{
string json = JsonConvert.SerializeObject(obj);
return json;
}
static T ReadObjectFromJsonString<T>(string json) where T: class
{
var obj = JsonConvert.DeserializeObject<T>(json);
return obj;
}
Then the class can be specified when you call those functions -
BatteryStatus status = new BatteryStatus(40);
string str = SaveObjectToJsonString<BatteryStatus>(status);
BatteryStatus readBack = ReadObjectFromJsonString<BatteryStatus>(str);
try this
BatteryStatus BatteryStatus = ((JObject)obj).ToObject<BatteryStatus>();
This is the solution I ended up with by combining information from the other answers (use of JObject and generics):
Add a generic wrapper function around the original ReadObjectFromJsonString function:
static T ReadObjectFromJsonString<T>(string json)
{
var obj = ReadObjectFromJsonString(json);
if (obj == null)
return default;
JObject jObj = obj is JObject ? (JObject)obj : JObject.FromObject(obj);
return jObj.ToObject<T>();
}
Then the main code will become quite clean, simple and logical:
static void Main(string[] args)
{
BatteryStatus batteryStatus = new BatteryStatus(40);
string json = SaveObjectToJsonString(batteryStatus);
batteryStatus = ReadObjectFromJsonString<BatteryStatus>(json);
}

C# Serialize nested lists as XML

I want to serialize a class to XML that has a field of type List{List{String}} or String[][] or List{String[]}. My class was serializing and deserializing fine before I added the nested collection field, but it is throwing an InvalidOperationException when serializing or deserializing now.
I don't really care if I have to use arrays or lists for this specific instance, but it would be nice to know a general solution that can be used for any nested collection situation.
Currently my field is declared like this:
[XmlElement("foo")]
public List<String[]> foo;
This has worked fine for me on single level lists and arrays in the past.
Here is the full class:
[XmlRoot("ColumnUpdaterPrefs")]
public class ColumnUpdaterPrefs : Prefs {
public ColumnUpdaterPrefs() : base() {
defaultHeaders = new List<String[]>();
}
[XmlAttribute("autoFill")]
public Boolean autoFill = true;
[XmlAttribute("allowErrors")]
public Boolean allowErrors;
[XmlAttribute("allowZeroes")]
public Boolean allowZeroes;
[XmlElement("defaultHeaders")]
public List<String[]> defaultHeaders;
[XmlElement("defaultKey")]
public String defaultKey;
public override Object Clone() {
return new ColumnUpdaterPrefs() {
autoFill = this.autoFill,
allowErrors = this.allowErrors,
allowZeroes = this.allowZeroes,
defaultHeaders = this.defaultHeaders,
defaultKey = this.defaultKey
};
}
}
And its base class:
[Serializable]
public abstract class Prefs : ICloneable {
[XmlAttribute("name")]
public String name;
public Prefs(String name = null) {
this.name = name;
}
public String Serialize() {
var xs = new XmlSerializer(this.GetType()); //InvalidOperationException occurs here
using (var sw = new StringWriter()) {
xs.Serialize(sw, this);
var result = sw.ToString();
return result;
}
}
public static TPrefs Deserialize<TPrefs>(String xml)
where TPrefs : Prefs {
var xs = new XmlSerializer(typeof(TPrefs)); //InvalidOperationException occurs here
using (var sr = new StringReader(xml)) {
var result = (TPrefs)(xs.Deserialize(sr));
return result;
}
}
public void Write(ApplicationSettingsBase settings, Boolean save = false, String name = null) {
if (settings == null) throw new ArgumentNullException("settings");
if (name == null) name = this.name;
settings[name] = Serialize();
if (save) settings.Save();
}
public static TPrefs Read<TPrefs>(ApplicationSettingsBase settings, String name)
where TPrefs : Prefs {
if (settings == null) throw new ArgumentNullException("settings");
return Deserialize<TPrefs>((String)settings[name]);
}
public static TPrefs ReadOrDefault<TPrefs>(ApplicationSettingsBase settings, String name)
where TPrefs : Prefs, new() {
try { return Read<TPrefs>(settings, name); }
catch { return new TPrefs() { name = name }; }
}
public abstract Object Clone();
}
Here are the exception details:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Xml.dll
Additional information: Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'System.Collections.Generic.List' to 'string[]'
error CS0029: Cannot implicitly convert type 'string[]' to 'System.Collections.Generic.List'
Is there a simple way to do this without creating a custom collection class?
thanks for the downvote, but it turns out the issue was just a matter of using the wrong attributes; something which could've been suggested based on my original code sample.
[XmlArray("outerList")]
[XmlArrayItem("innerList", typeof(List<String>))]
public List<List<String>> foo;

Deserialize list of JSON objects

I got a Windows Phone 8.1 app.
I am trying to parse a list of objects returned by my Web API call.
On my server I have this code:
Default.aspx:
[WebMethod]
public static List<Shared.PremisesResponse> GetPremises(string emailaddress)
{
Premises premises = new Premises();
return premises.GetPremises(emailaddress);
}
In that premise object class
public List<Shared.PremisesResponse> GetPremises(string emailAlias)
{
DAL dal = new DAL();
List<Shared.PremisesResponse> premises = new List<Shared.PremisesResponse>();
try
{
DataSet dtMacs = dal.GetMacs(emailAlias);
for (int index = 0; index < dtMacs.Tables[0].Rows.Count; index++)
{
Shared.PremisesResponse itemMAC1 = new Shared.PremisesResponse();
itemMAC1.PremiseName = dtMacs.Tables[0].Rows[index]["PremiseName"].ToString().Trim();
itemMAC1.Alias = dtMacs.Tables[0].Rows[index]["Alias"].ToString().Trim();
premises.Add(itemMAC1);
}
}
catch (Exception ex)
{
Email2.SendError("Premises.GetPremises:" + ex.ToString(), emailAlias);
Shared.PremisesResponse itemMAC1 = new Shared.PremisesResponse();
itemMAC1.PremiseName = "ERROR";
itemMAC1.Alias = ex.ToString();
premises.Add(itemMAC1);
}
return premises;
}
The class Shared.Premise:
public class PremisesResponse
{
public string PremiseName;
public string Alias;
}
In my WP8.1 client app:
public async static Task<List<D2>> GetPremises( string emailaddress)
{
List<D2> premises = new List<D2>();
try
{
using (var client = new HttpClient())
{
var resp = await client.PostAsJsonAsync("http://my url/NativeApp/Default.aspx/GetPremises",
new { emailaddress = emailaddress });
var str = await resp.Content.ReadAsStringAsync();
var premisesResponse = JsonConvert.DeserializeObject<List<D2>>(str);
foreach (var pr in premisesResponse)
{
D2 d2 = new D2();
d2.Alias = pr.Alias;
d2.PremiseName = pr.PremiseName;
premises.Add(d2);
}
}
}
catch (Exception ex)
{
//evMessage(Enums.MessageType.Error, serverRegister);
}
return premises;
}
And the objects I am using in my client:
public class D2
{
public string __type { get; set; }
public string PremiseName;
public string Alias;
}
public class PremisesResponse
{
public D2 d { get; set; }
}
'var str' returns this value:
{"d":[{"__type":"InformedMotionBiz.Shared+PremisesResponse","PremiseName":"Informatica 2000","Alias":"9A5C3-E1945-3D315-BB43C"},{"__type":"InformedMotionBiz.Shared+PremisesResponse","PremiseName":"My Office","Alias":"40387-69918-FC22F-C444B"}]}
The error occurs on this line:
var premisesResponse = JsonConvert.DeserializeObject<List<PremisesResponse>>(str);
The error message is:
[Informed.D2]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'd', line 1, position 5.
I have no problems returning a single value, just with returning a list of this object.
Any pointers would be helpful.
Thanks
You're trying to deserialize a List<D2> rather than a single D2 object:
public class PremisesResponse
{
public D2[] d { get; set; }
}
And then simply:
PremisesResponse response = JsonConvert.DeserializeObject<PremisesResponse>(str);

An exception of type 'System.InvalidOperationException' occurred in System.Web.Extensions.dll but was not handled in user code

Why do have this error on this part of the code ?
this part
var data = serializer.Deserialize<EmailTemplate>(httpRequest.Form["data"].ToString());
my procedure
public int UpdateEmailTemplate()
{
HttpResponseMessage result = null;
ObjectService uploadFile = new ObjectService();
List<ActiveUp.Net.Mail.Attachment> attachment = new List<ActiveUp.Net.Mail.Attachment>();
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Form["data"] != null)
{
var serializer = new JavaScriptSerializer();
var data = serializer.Deserialize<EmailTemplate>(httpRequest.Form["data"].ToString());
if (httpRequest.Files.Count > 0)
{
var docfiles = new List<string>();
foreach (string file in httpRequest.Files)
{
MemoryStream target = new MemoryStream();
httpRequest.Files[file].InputStream.CopyTo(target);
uploadFile.AddObject(data.Id, "SU_ENTITY_MSG_TEMPLATE","", target.GetBuffer(), httpRequest.Files[file].FileName);
}
}
AdminService List = new AdminService();
return List.UpdateEmailTemplate(data);
}
MY class
public class EmailTemplate
{
public int Id;
public string TypeObject;
public int? idObject;
public string ObjectName;
public string IdTeam;
public string IdTask;
public string Team;
public string task;
public string Title;
public string Subject;
public string dataHtml;
public List<Objects> fileListRequest;
}
It's pretty plainly saying that the contents of:
httpRequest.Form["data"]
...is an array of some sort. Adding .ToString() will just return it's type name. Passing that to Deserialize is what's giving you the error, as Deserialize is expecting an array and just getting a string.
Try taling the .ToString() off - this may not work. If it doesn't you'll have to convert httpRequest.Form["data"] to what ever data type you've put into it (whuich you do not say).

Problem xml-deserializing recursive nested object

Solved: code below is not causing an infinite loop as I thought. the loop was in the code calling the deserialization. this posted code works just fine
I am trying to serialize and deserialize to xml the following object
public class MessageObjectCollection : List<MessageObject>
{
public string Serialize()
{
return XmlObjectSerializer.SerializeObject(this);
}
public static MessageObjectCollection DeSerialize(string serializedPriceHistory)
{
return XmlObjectSerializer.DeserializeObject<MessageObjectCollection>(serializedPriceHistory);
}
}
The MessageObject class looks like this
public class MessageObject
{
public string Title;
public MessageObjectCollection Responses;
}
So if I have a instance of messageobjectcollection that looks like:
var msgColl = new MessageObjectCollection
{
new MessageObject
{
Title = "Hello",
Responses = new MessageObjectCollection
{
new MessageObject
{
Title = "hi",
Responses = null
}
}
}
}
I can serialize this just fine by calling
var xml = msgColl.Serialize();
However when I try to deserialize this by calling
var msgColl = new MessageObjectCollection().Deserialize(xml);
I get an stack overflow exception in the deserialization method:
public static T DeserializeObject<T>(string xml)
{
T result;
var ser = new XmlSerializer(typeof(T));
var buffer = StringToUTF8ByteArray(xml);
using (var stream = new MemoryStream(buffer, 0, buffer.Length))
{
result = (T) ser.Deserialize(stream);
}
return result;
}
Anyone know what I'm doing wrong?
Im not sure if its relevant to the problem but as the Deserialize method is static shouldn't you be calling...
var msgColl = MessageObjectCollection.Deserialize(xml);
instead of...
var msgColl = new MessageObjectCollection().Deserialize(xml);
??

Categories