I have the following structure in my json file
"missionName": "missionname",
"thumb_image": "pics/mission-info.png",
"uplinkPage": [
{
"RPC": {
"name": "RPC",
"rpc": "",
"args": ""
},
"EXE": {
"name": "app1",
"prog": "",
"args": ""
},
"VM": {
"name": "VM",
"name": "",
"args": ""
},
"JAR": {
"name": "JAR",
"prog": "",
"args": ""
},
"link": {
"name": "somelink",
"url": ""
}
}
],
for this I have the following class
public class EXE
{
public string name { get; set; }
public string prog { get; set; }
public string args { get; set; }
}
public class RPC
{
public string name { get; set; }
public string rpc { get; set; }
public string args { get; set; }
}
public class VM
{
public string name { get; set; }
public string args { get; set; }
}
public class JAR
{
public string name { get; set; }
public string prog { get; set; }
public string args { get; set; }
}
public class Link
{
public string name { get; set; }
public string url { get; set; }
}
public class UplinkPage
{
public VM[] vmList { get; set; }
public EXE[] exeList { get; set; }
public RPC[] rpcList { get; set; }
public JAR[] jarList { get; set; }
public Link[] linkList { get; set; }
}
public class Rootobject
{
public string missionName { get; set; }
public string thumb_image { get; set; }
public Uplinkpage[] uplinkPage { get; set; }
}
the uplinkPage section can have one or many of each of the EXE, RPC, VM .. sections. I have tried to add multiply sections like this
"EXE": {
"1": {
"name": "app1",
"data-prog": "",
"data-args": ""
},
"2": {
"name": "app2",
"data-prog": "",
"data-args": ""
}
}
when I do the deserialization as so
Rootobject page = JsonConvert.DeserializeObject<Rootobject>(File.ReadAllText("mission1.json"));
I get an object and I can read everything except if I have multiply values of the same type, I will only get one of them. If I declare sections as array
public EXE[] exeList { get; set; }
I will get the last one and if as
Dictionary<string,EXE> exeList {get; set;}
I will get the first one. I have noticed that when I use the dictionary the type of the EXE changes to EXE1.
So I was wondering what am I doing wrong? am I mission some thing here?
cheers,
es
Whenever you have a JSON property that might be duplicated, it will be easiest to represent the value of that property as JSON array, rather than multiple properties with duplicated names. I.e. instead of
{
"EXE" : {"id":1},
"RPC" : {"name":"a"},
"EXE" : {"id":2},
}
You want to do:
{
"EXE" : [{"id":1}, {"id":2}],
"RPC" : [{"name":"a"}]
}
Similarly, in the VM class, name appears multiple times, so name should be an array as well:
public class VM
{
public string [] name { get; set; }
public string args { get; set; }
}
(It's not impossible to deserialize duplicated property names, just difficult, and requires a custom converter. See How to deserialize JSON with duplicate property names in the same object. Since you control your JSON format, I'd recommend avoiding this. Using a nested object with indexed properties as you propose in your question is also an option; it is less difficult but still requires custom conversion. See How to parse this JSON using Newton Soft for nested object. But using a JSON array is easiest.)
Next, you need to tell Json.NET how to map c# property names to JSON property names when they are inconsistent. For instance, in your JSON you have a property "EXE" but in c# the property name is public EXE[] exeList { get; set; }. You can either rename the JSON properties, rename the c# properties, or make the mapping using [JsonProperty]:
public class UplinkPage
{
[JsonProperty("VM")]
public VM[] vmList { get; set; }
[JsonProperty("EXE")]
public EXE[] exeList { get; set; }
[JsonProperty("RPC")]
public RPC[] rpcList { get; set; }
[JsonProperty("JAR")]
public JAR[] jarList { get; set; }
[JsonProperty("link")]
public Link[] linkList { get; set; }
}
I notice also that your EXE object sometimes has a "data-prog" property, and sometimes just a "prog". You should standardize on one.
Thus your JSON should look like:
{
"missionName": "missionname",
"thumb_image": "pics/mission-info.png",
"uplinkPage": [
{
"RPC": [
{
"name": "RPC",
"rpc": "",
"args": ""
}
],
"EXE": [
{
"name": "app1",
"prog": "prog1",
"args": "args1"
},
{
"name": "app2",
"prog": "prog2",
"args": "args2"
}
],
"VM": [
{
"name": [
"VM",
""
],
"args": ""
}
],
"JAR": [
{
"name": "JAR",
"prog": "",
"args": ""
}
],
"link": [
{
"name": "somelink",
"url": ""
}
]
}
]
}
And your classes should look like:
public class EXE
{
public string name { get; set; }
public string prog { get; set; }
public string args { get; set; }
}
public class RPC
{
public string name { get; set; }
public string rpc { get; set; }
public string args { get; set; }
}
public class VM
{
public string [] name { get; set; }
public string args { get; set; }
}
public class JAR
{
public string name { get; set; }
public string prog { get; set; }
public string args { get; set; }
}
public class Link
{
public string name { get; set; }
public string url { get; set; }
}
public class UplinkPage
{
[JsonProperty("VM")]
public VM[] vmList { get; set; }
[JsonProperty("EXE")]
public EXE[] exeList { get; set; }
[JsonProperty("RPC")]
public RPC[] rpcList { get; set; }
[JsonProperty("JAR")]
public JAR[] jarList { get; set; }
[JsonProperty("link")]
public Link[] linkList { get; set; }
}
public class Rootobject
{
public string missionName { get; set; }
public string thumb_image { get; set; }
public UplinkPage[] uplinkPage { get; set; }
}
prototype fiddle.
Related
here Is my Models ,here in my model PK is decorated with Key becoz in EF it must be . But as it is aslo available in base class. if I removed PK from Person it gives error as model has not assign a Key IN EF which is strange to me .
public class Person:TBase
{
[Key]
public long PK { get; set; }
public string NAME { get; set; }
public string ADDRESS { get; set; }
}
public class TBase: Base
{
public virtual long? FKTenant { get; set; }
public virtual bool IsDefault { get; set; }
}
public class Base
{
[Key]
public long PK { get; set; }
public virtual string GlobalID { get; set; }
}
and Controller
[EnableQuery]
public IHttpActionResult Get()
{
try
{
IQueryable<Person> result;
var result = DbContext.Persons.Where(x => x.FKTenant == context.FKTenant).ToList();
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
i am getting response in postman is
"value": [
{
"#odata.etag": "W/\"bnVsbA==\"",
"PK": 1001,
"NAME": "VIVEK",
"ADDRESS": "DELHI",
"FKTenant":null,
"IsDefault ":null,
"GlobalID ":null
}]
But my Intention to get ouput response as below which should contain onlly name and address
"value": [
{
"#odata.etag": "W/\"bnVsbA==\"",
"NAME": "VIVEK",
"ADDRESS": "DELHI"
}]
Any guide will be appreciable.
You should use a ViewModel
write another class as ViewModel and when you want return object first map to new ViewModel then return it.
// Json
{
"application": [
"java.util.arraylist",
[
{
"applicationId": "XXXX"
}
]
],
"applicationType": "ZZZZ",
"functionType": "YYYY"
}
I have created the below property for above JSON
public class Root
{
public Application[] Application { get; set; }
public string ApplicationType { get; set; }
public string FunctionType { get; set; }
}
public class Application
{
public string something { get; set; }
public SubApplication[] SubApplicationItem { get; set; }
}
public class SubApplication
{
public string applicationId { get; set; }
}
Not sure how should I create a property for below part of the JSON, Can someone please share your thoughts on this
[
"java.util.arraylist",
[
I have a blazor component that I want to pass data retreived from a backend. Each set of data has a different entity name so I'm having trouble converting the entity to a generic type when it gets to the component. Where is my error? Thanks
Getting the following error on ChildData=#sysList in the parent:
Argument1: Cannot convert from Test2.Shared.Models.MeasurementSystem[] to System.Collections.Generic.IReadOnlyList[]
Parent
<ChildComponent ChildData=#sysList TItem=#Test2.Shared.Models.MeasurementSystem</ChildComponent>
<ChildComponent ChildData=#unitList TItem=#Test2.Shared.Models.MeasurementUnit</ChildComponent>
<ChildComponent ChildData=#groupList TItem=#Test2.Shared.Models.MeasurementGroup</ChildComponent>
#functions {
private Test2.Shared.Models.MeasurementSystem[] sysList { get; set; }
private Test2.Shared.Models.MeasurementUnit[] unitList { get; set; }
private Test2.Shared.Models.MeasurementGroup[] groupList { get; set; }
protected override async Task OnInitAsync()
{
sysList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementSystem[]>("/api/System/Index");
unitList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementUnit[]>("/api/Unit/Index");
groupList = await Http.GetJsonAsync<Test2.Shared.Models.MeasurementGroup[]>("/api/Group/Index");
}
}
Child
#typeparam TItem
#foreach (var data in ChildData)
{
<p #data.Name>
}
#functions {
[Parameter] private IReadOnlyList<TItem>[] ChildData { get; set; }
}
Classes
public class MeasurementSystem
{
public int SystemId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
public class MeasurementUnit
{
public int UnitId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Factor { get; set; }
public int Magnitude { get; set; }
}
}
public class MeasurementGroup
{
public int GroupId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
}
I'm having a hard time figuring out how to do queries with levels of alternating collection and navigation properties with proxy and lazy loading disabled to serialize the result.
public ApplicationDbContext()
: base("Debug")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
The entities look like this (omitting non-navigation or non-collections):
public class Comprobante: ComprobanteGeneric
{
}
public class ComprobanteGenericStructure
public int Id { get; set; }
[Required]
public virtual Conceptos Conceptos { get; set; }
}
public class Conceptos
{
public Conceptos()
{
Concepto = new List<Concepto>();
}
[ForeignKey("Comprobante")]
public int Id { get; set; }
[Required]
public virtual ICollection<Concepto> Concepto { get; set; }
public virtual Comprobante Comprobante { get; set; }
}
public class Concepto :RelatedComprobante
{
[Key]
public int Id { get; set; }
public virtual OrderOfImpuestosForConceptos Impuestos { get; set; }
public virtual Conceptos Conceptos { get; set; }
}
public class RelatedComprobante
{
[ForeignKey("Comprobante")]
public int ComprobanteId { get; set; }
public virtual Comprobante Comprobante { get; set; }
}
public class OrderOfImpuestosForConceptos : RelatedComprobante
{
public int Id { get; set; }
public virtual TrasladosNode Traslados { get; set; }
public virtual Retenciones Retenciones { get; set; }
}
public class TrasladosNode : RelatedComprobante
{
public TrasladosNode()
{
Traslado = new HashSet<Traslado>();
}
[Key]
public int Id { get; set; }
[Required]
public virtual ICollection<Traslado> Traslado { get; set; }
}
public class Traslado : RelatedComprobante
{
public int Id { get; set; }
public virtual TrasladosNode TrasladosNode { get; set; }
}
public class Retenciones : RelatedComprobante
{
public Retenciones()
{
Retencion = new List<Retencion>();
}
public int Id { get; set; }
[Required]
public virtual ICollection<Retencion> Retencion { get; set; }
}
public class Retencion : RelatedComprobante
{
public int Id { get; set; }
public virtual Retenciones Retenciones { get; set; }
}
I need the whole graph. With lazy loading enabled it returns it all eventually but serialization takes several seconds and several queries to DB. I disabled it and tried the following query:
comprobantes = _db.Comprobante
.Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos.Retenciones).Select(r=>r.Retencion))
.Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos.Traslados).Select(t => t.Traslado));
However I get an empty concepto list:
[{
"id": 324,
"conceptos": {
"concepto": []
}
},
{
"id": 340,
"conceptos": {
"concepto": []
}
}
}]
Even simpler queries like the following yield the exact same results:
comprobantes = _db.Comprobante
.Include(c => c.Conceptos.Concepto.Select(co => co.Impuestos));
I know is not the serialization for when I inspect the object while debugging is empty:
What am I doing wrong?
Thanks to David comment I was able to build a working query(es):
var comprobantes = _db.Comprobante
.Include(b => b.Conceptos.Concepto.Select(c => c.Impuestos.Retenciones.Retencion))
.Include(b => b.Conceptos.Concepto.Select(c => c.Impuestos.Traslados.Traslado));
foreach (var comprobante in comprobantes)
{
_db.ComprobanteTraslado.Where(t => t.ComprobanteId == comprobante.Id);
_db.ComprobanteRetencion.Where(r => r.ComprobanteId == comprobante.Id);
}
I'd like to be able to have the code below
[Route("/Incidents", "Get")]
public class GetViewConfig
{
public List<Filter> Filters { get; set; }
}
public class Filter
{
public string Property { get; set; }
public FilterType Type { get; set; }
public string Value { get; set; }
}
public enum FilterType
{
IsBetween,
Is,
IsNot
}
public class GetViewConfigResponse
{
public List<Filter> Filters { get; set; }
}
public class ViewConfigService : Service
{
public object Get(GetViewConfig request)
{
return null;
}
}
Show all the values for the FilterType on the metadata page. Is there a way to do this?
Not on the metadata pages, but you can view this using the Swagger API and the [ApiAllowableValues] attribute, e.g:
[Api("Service Description")]
[Route("/swagger/{Name}", "GET", Summary = #"GET Summary", Notes = "GET Notes")]
public class MyRequestDto
{
[ApiMember(Name="Name", Description = "Name Description",
ParameterType = "path", DataType = "string", IsRequired = true)]
[ApiAllowableValues("Name", typeof(Color))] //Enum
public string Name { get; set; }
}