Convert dynamic object to IEnumerable Issue - c#

protected override IEnumerable<dynamic> GetData()
{
var request = new RestRequest();
var directoryResponse = client.ExecuteTaskAsync(request).Result;
dynamic directory = JsonConvert.DeserializeObject<MyDTO>(directoryResponse.Content);
cachedDirectory = directory;
}
return cachedDirectory;
Issue is on the line
cachedDirectory = directory;
Whenever it tries convert the dynamic object to an IEnumerable type.
Exception message:
Cannot implicitly convert type 'MyDTO' to 'System.Collections.Generic.IEnumerable<object>'. An explicit conversion exists (are you missing a cast?)

I have to make few assumption.
I assume that your cachedDirectory object is type of IEnumerable. If this is the case then it is clear that it can not convert MyDTO object to IEnumerable at runtime and it throw exception.
Following code give you error. I assume that you need enumrable.
public class NewTest
{
IEnumerable<dynamic> cachedDirectory;
public IEnumerable<dynamic> GetData()
{
dynamic directory = JsonConvert.DeserializeObject<MyDTO>("{ 'Name' : 'Test' }");
cachedDirectory = directory;
return cachedDirectory;
}
}
public class MyDTO
{
public string Name { get; set; }
}
// This is how you call. (This code give error)
NewTest test = new NewTest();
IEnumerable<dynamic> result = test.GetData();
Answer : If above is the way you use then you can do something like this.
public class NewTest
{
IEnumerable<dynamic> cachedDirectory;
public IEnumerable<dynamic> GetData()
{
var request = new RestRequest();
var directoryResponse = client.ExecuteTaskAsync(request).Result;
dynamic directory = JsonConvert.DeserializeObject<IEumerable<MyDTO>>(directoryResponse.Content);
return directory;
}
}
public class MyDTO
{
public string Name { get; set; }
}
// Now this will work.
NewTest test = new NewTest();
IEnumerable<dynamic> result = test.GetData();

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);
}

SerializedObject is not defined in a referenced assembly c#

I seem to be having difficulty writing my object list to NSUserDefaults using a SerializedObject method that only returns the error "The type 'Object' is defined in an assembly not referenced. You must add a reference to assembly 'netstandard'". I don't understand what this means and how to fix it.
The list I want to serialize:
public class doubleVariableDateAndName
{
public string Name;
public DateTime DueDay;
}
public List<doubleVariableDateAndName> reminderList = new List<doubleVariableDateAndName>();
How I am serializing it:
public void SaveList(List<doubleVariableDateAndName> reminderList)
{
var serializedContent = JsonConvert.SerializeObject(reminderList);
NSUserDefaults.StandardUserDefaults.SetString(serializedContent, "remindersStored");
}
And how I am deserializing it:
public List<doubleVariableDateAndName> GetReminderList()
{
var userDefaults = NSUserDefaults.StandardUserDefaults;
var serializedContent = userDefaults.StringForKey("remindersStored");
if (!string.IsNullOrEmpty(serializedContent))
{
var reminderList = JsonConvert.DeserializeObject<List<doubleVariableDateAndName>>(serializedContent);
return reminderList;
}
return null;
}
Thanks in advance!

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).

Categories