I have this json
{
"query":{
"allcategories":{
"accontinue":"!!!_songs"
}
}
}
here are the c# classes:
public class Allcategories
{
public string accontinue { get; set; }
}
public class Query
{
public Allcategories allcategories { get; set; }
}
public class RootObject
{
public Query query { get; set; }
}
can i map this somehow the following C# classes? I want to skip one level, and reduce nesting of json like this:
public class Query
{
[JsonAttribute("allcategories.accontinue")]
public string accontinue { get; set; }
}
public class RootObject
{
public Query query { get; set; }
}
Your suggested code is valid and would reduce nesting, but accontinuewould no longer be an Allcategories object, it would be a string attribute of Query.
Related
I have a xml format in following format mentioned below:-
<JobRunnerPluginStaus PluginName="JobRun">
<JobstepStatus>
<JobStatus StepNumber="1" StepStatus="Done"/>
<JobStatus StepNumber="2" StepStatus="Started" />
</JobstepStatus>
</JobRunnerPluginStaus>
I want to get it converted to following class object using Generics and Reflection.
I want to convert the attributes to simple type(PluginName) and the nested property to a list object(JobstepStatus).
public class JobRunnerPluginStaus
{
public List<JobStatus> JobstepStatus { get; set; }
public string PluginName { get; set; }
}
public class JobStatus
{
public int StepNumber { get; set; }
public string StepStatus { get; set; }
}
I mostly use sites like: https://xmltocsharp.azurewebsites.net/
to do the dirty work for me.
Below is how your class hierarchy would look like:
[XmlRoot(ElementName="JobStatus")]
public class JobStatus {
[XmlAttribute(AttributeName="StepNumber")]
public string StepNumber { get; set; }
[XmlAttribute(AttributeName="StepStatus")]
public string StepStatus { get; set; }
}
[XmlRoot(ElementName="JobstepStatus")]
public class JobstepStatus {
[XmlElement(ElementName="JobStatus")]
public List<JobStatus> JobStatus { get; set; }
}
[XmlRoot(ElementName="JobRunnerPluginStaus")]
public class JobRunnerPluginStaus {
[XmlElement(ElementName="JobstepStatus")]
public JobstepStatus JobstepStatus { get; set; }
[XmlAttribute(AttributeName="PluginName")]
public string PluginName { get; set; }
}
In my method I got back results that contain several list of strings and list of complex type objects.
var AcctLst = gd.validateGroupMembershipUploadDetails(_input);
Mapper.CreateMap<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>();
var result = Mapper.Map<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>(AcctLst);
return result;
var AcctLst contains the sample data :
Data.Entities.Upload.GroupMembershipValidationOutput
and
Business.Upload.GroupMembershipValidationOutput
looks like
public class GroupMembershipValidationOutput
{
public List<string> _validMasterIds { get; set; }
public List<ChapterCodeValidationOutput> _validChapterCodes { get; set; }
public List<GroupCodeValidationOutput> _validGroupCodes { get; set; }
public List<string> _invalidMasterIds { get; set; }
public List<string> _invalidChapterCodes { get; set; }
public List<string> _invalidGroupCodes { get; set; }
}
public class ChapterCodeValidationOutput
{
public string chpt_cd { get; set; }
public string appl_src_cd { get; set; }
}
public class GroupCodeValidationOutput
{
public string grp_cd { get; set; }
public string grp_nm { get; set; }
}
I guess _validChapterCodes and _validGroupCodes throw the following exception :
Missing type map configuration or unsupported mapping.
Mapping types:
ChapterCodeValidationOutput -> ChapterCodeValidationOutput
ARC.Donor.Data.Entities.Upload.ChapterCodeValidationOutput -> ARC.Donor.Business.Upload.ChapterCodeValidationOutput
Destination path:
GroupMembershipValidationOutput._validChapterCodes._validChapterCodes._validChapterCodes0[0]
Source value:
ARC.Donor.Data.Entities.Upload.ChapterCodeValidationOutput
Yeah damn. It's relatively simple. You just have to map the inner nested types first.
var AcctLst = gd.validateGroupMembershipUploadDetails(_input);
Mapper.CreateMap<Data.Entities.Upload.ChapterCodeValidationOutput, Business.Upload.ChapterCodeValidationOutput>();
Mapper.CreateMap<Data.Entities.Upload.GroupCodeValidationOutput, Business.Upload.GroupCodeValidationOutput>();
Mapper.CreateMap<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>();
var result = Mapper.Map<Data.Entities.Upload.GroupMembershipValidationOutput, Business.Upload.GroupMembershipValidationOutput>(AcctLst);
return result;
Then it works flawlessly.
I'm trying to create some interfaces. The IReportSection object will have one string and a collection of items, which could be different depending on what we're working with. Do I need to make it generic?
The IReport will have one string and a collection of IReportSection.
Here's how I'm trying to define it now.
public interface IReport
{
string ReportName { get; set; }
ICollection<IReportSection> ReportSections { get; }
}
public interface IReportSection
{
string ReportSectionName { get; set; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase : IReportSection
{
public string ReportSectionName { get; set; }
public ICollection ReportItems { get; set; }
}
And my models:
pulic class ProjectSubmissionViewModel
{
public int ProjectSubmissionId { get; set; }
public string SubmissionTitle { get; set; }
}
pulic class AffiliateViewModel
{
public int AffiliateId { get; set; }
public string AffiliateName { get; set; }
}
This is how I'm trying to use it in code:
public class ChapterAffiliates : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Affiliates"; } }
public ICollection<AffiliateViewModel> ReportItems { get; set; }
}
public class ChapterTitles : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Titles"; } }
public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
}
public class SubmissionListViewModel : IReport
{
public ICollection<ProjectSubmissionViewModel> Submissions { get; set; }
public ICollection<AffiliateViewModel> Affiliates{ get; set; }
public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections
{
get
{
var affiliateSection = new ChapterAffiliates
{
ReportItems = Affiliates
};
var titleSection = new ChapterTitles
{
ReportItems = Submissions.Where(s => s.SubmissionTitle.Contains("SomePhrase")).ToList()
};
var sections = new List<IReportSection> { {subSection}, {titleSection} };
return sections;
}
}
}
I'm not sure how to best define this. I'm pretty sure I've done it before, but it's not coming to me.
Are the type parameters for TRType all the same within a certain report? E.g. will you have report sections with different report types in them?
If all types within a report are the same, the solution is relatively simple:
public interface IReport<T> { ... }
If this is not the case - you'll have to do something different, e.g:
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase<TRType> : IReportSection {
...
}
This allows you to put different underlying types in the ReportSections collection related to the report. You'll have to do some more work to get the exact information that you need out of each report section.
JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
// Deserialize the response to get an array of CUSTOM Cases
var reportsList = jsSerializer.Deserialize<SfdcObjects.SfdcCollection<SfdcObjects.Assets>>(HttpUtility.UrlDecode(response));
throws an exception:
Error: System.InvalidOperationException: Type 'SalesforceDataQueryComponent.Utils.SfdcObjects+SfdcCollection`1[
[SalesforceDataQueryComponent.Utils.SfdcObjects+Assets, SalesforceDataQueryComponent, Version=1.2.0.0, Culture=neutral]]'
is not supported for deserialization of an array.
I can not figure it out the issue:
Objects:
namespace SalesforceDataQueryComponent.Utils
{
class SfdcObjects
{
// Used for Authentication
public class TokenResponse
{
public string id { get; set; }
public string issued_at { get; set; }
public string refresh_token { get; set; }
public string instance_url { get; set; }
public string signature { get; set; }
public string access_token { get; set; }
}
// All classes shown next are used to parse the HttpGet Response
public class SfdcCollection<T>
{
public bool Done { get; set; }
public int Size { get; set; }
public string NextRecordsUrl { get; set; }
public List<T> Records { get; set; }
}
public class SfdcAttributes
{
public string Type { get; set; }
public string Url { get; set; }
}
public class Accounts : Account
{
public SfdcAttributes Attributes { get; set; }
}
public class Assets : Asset
{
public SfdcAttributes Attributes { get; set; }
}
public class CustomAssets : Assets
{
public string StringInstallDate { get; set; }
}
public class Users : User
{
public SfdcAttributes Attributes { get; set; }
}
public class CustomCase : Case
{
public string StringCreatedDate { get; set; }
}
public class CustomCases : CustomCase
{
public SfdcAttributes Attributes { get; set; }
}
}
}
You do not include your response JSON in your question, however from the error message, your problem must be that the root JSON container in your response is an array. A JSON array, according to the JSON standard, looks like this:
[value1, value2, ..., valueN]
JSON serializers map types that implement ICollection or IEnumerable from and to JSON arrays.
Your root object SfdcCollection<T>, however, is NOT a collection or enumerable, despite its name. Instead it's a non-enumerable generic POCO:
public class SfdcCollection<T> // No IEnumerable<T>
{
public bool Done { get; set; }
public int Size { get; set; }
public string NextRecordsUrl { get; set; }
public List<T> Records { get; set; }
}
Thus a serializer will map this to a JSON object (which is a set of key/value pairs and looks like {"name1" : value1, "name2" : value2, ..., "nameN" : valueN }) instead of an array.
You need to update your data model to the JSON you are actually receiving. Try uploading your JSON to http://json2csharp.com/, it will automatically generate classes for you.
If you must use the classes in your question, you could ask another question about how to map the JSON you are actually receiving onto your required classes, using your desired serializer (e.g. Json.NET, DataContractJsonSerializer, JavaScriptSerializer, or etc.)
Here is the class I'm trying to create.
I get the error 'DbMainContext does not contain a definition for tName' It's the 3rd line under the using statement below.
I don't want to have to keep recoding the query in a lot of places, so it seemed like a helper method would keep the code cleaner.
public class DbHelper
{
static string GetValueFromDatabase(DatabaseData dbData)
{
string tName = dbData.TableName;
using (DbMainContext db = new DbMainContext())
{
var query =
(from t in db.tName
where t.ID == 1198
select t.LastName).Single<String>();
return query;
}
}
}
public class DatabaseData : IDatabaseData
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string WhereClause { get; set; }
public int WhereId { get; set; }
}
public interface IDatabaseData
{
public string TableName { get; set; }
public string ColumnName { get; set; }
public string WhereClause { get; set; }
public int WhereId { get; set; }
}
}
You're perhaps looking for something like How to generalise access to DbSet members of a DbContext?.
You can't use db."Users", so you can't use db.tName either. You could use reflection for that, but you don't want that.