c# wcf service deserialize json array of arrays using json.net - wcf

i'm developing a mobile air application. for comunications i'm using a wcf service.
now my problem is this, i'm trying to deserialize an array of arrays using json.net. the sub arrays are typed.
so, my classes in the mobile side are the following:
package Model.VO.PHCDATA
{
[Bindable]
[RemoteClass(alias="Model.PCHModel.VODadosPHC")]
public class VoBi
{
private var _BIstamp:String;
private var _ivaincl:Number;
private var _vendnm:String;
private var _vendedor:Number;
private var _iva:Number;
private var _lordem:Number;
private var _tabiva:Number;
private var _txiva:Number;
private var _familia:String;
....
}
}
and the other is:
package Model.VO.PHCDATA
{
[Bindable]
[RemoteClass(alias="Model.PCHModel.VODadosPHC")]
public class VOBO
{
private var _BOstamp:String;
private var _vendedor:Number;
private var _vendnm:String;
....
}
}
and the corresponding c# classes are the following:
[DataContract(Name = "VoBi")]
public class VoBi
{
[DataMember(IsRequired = true, Name = "BIstamp", Order = 0)]
public string BIstamp { get; set; }
[DataMember(IsRequired = true, Name = "ivaincl", Order = 1)]
public decimal ivaincl { get; set; }
[DataMember(IsRequired = true, Name = "vendnm", Order = 2)]
public string vendnm { get; set; }
[DataMember(IsRequired = true, Name = "vendedor", Order = 3)]
public decimal vendedor { get; set; }
....
}
and the other one:
[DataContract(Name = "VOBO")]
public class VOBO
{
[DataMember(IsRequired = true, Name = "BOstamp", Order = 0)]
public string BOstamp { get; set; }
[DataMember(IsRequired = true, Name = "vendedor", Order = 1)]
public decimal vendedor { get; set; }
[DataMember(IsRequired = true, Name = "vendnm", Order = 2)]
public string vendnm { get; set; }
[DataMember(IsRequired = true, Name = "nmdos", Order = 3)]
public string nmdos { get; set; }
[DataMember(IsRequired = true, Name = "ndos", Order = 4)]
public decimal ndos { get; set; }
.....
}
the corresponding json string to be sent to the server is this one:
{
"DADOSBI": [
{
"edebito": 0,
"desconto": 92.121,
"vendedor": 0,
"desc2": 222.343,
"iva": 23,
"ettdeb": 123.555,
"lordem": 12,
"tabiva": 2.1,
....
},
{
"edebito": 0,
"desconto": 92.121,
"vendedor": 1,
"desc2": 222.343,
"iva": 23,
"ettdeb": 123.555,
"lordem": 12,
"tabiva": 2.1,
....
}
],
"DADOSBO": [
{
"estab": 123.88,
"etotaldeb": 123,
"obs": "",
"vendedor": 0,
"statuspda": "qqqqqqqqqqqq",
"ebo_2tvall": 12,
"ebo_2tdes1": 12.11,
...
},
{
"estab": 123.88,
"etotaldeb": 123,
"obs": "",
"vendedor": 1,
"statuspda": "qqqqqqqqqqqq",
"ebo_2tvall": 12,
....
}
]
}
how do i handle this? do i use json.net CustomCreationConverter to deserialize the data? and obtain the corresponding arrays filled with the classes i've mentioned, or i use another approach?
help would be appreciated.
thanks in advance.

Assuming your top class looks as follows (if you do not have then create one if it is effort less otherwise we need to go a better solution)
internal class TopClass
{
[JsonProperty("DADOSBI")]
public IList<VoBi> VOBiList { get; set; }
[JsonProperty("DADOSBO")]
public IList<VOBO> VOBOList { get; set; }
}
Then simply deserialise using
var topClass = JsonConvert.DeserializeObject<TopClass>( json);
If this is not the answer you are looking for then please update the question with more information

Related

How to deserialize object as single item list?

I need to make a service that allows both next jsons as request body
{
"id": 1,
...
"foo": null
}
and
{
"id": [1, 2, 3],
...
"foo": null
}
I tried making the model like this
public class MyModel
{
public List<int> Id { get; set; }
//...
public string Foo { get; set; }
}
which works for the second case, but not for the first one, as an int is not a list of ints.
What can I do to be able to parse both bodies correctly?
You could deserialize into a dynamic object instead.
dynamic result = JsonConvert.DeserializeObject<dynamic>(json);
Another approach I'm not sure would work is to make the Id property dynamic.
public class MyModel
{
public dynamic Id { get; set; }
public string Foo { get; set; }
}
You can create Models like the following(Model includes all the properties except id):
public class MyModel
{
public List<int> id { get; set; }
public Model model { get; set; }
}
public class Model
{
//...
public string foo { get; set; }
}
And ckeck id in requestbody,if id is int type,create a new list and add id to the list.
MyModel myModel = new MyModel();
myModel.model=JsonConvert.DeserializeObject<Model>(jsonResult);
var mydata = JsonConvert.DeserializeObject<JObject>(jsonResult);
if (!mydata["id"].ToString().Contains("["))
{
myModel.id = new List<int> { Convert.ToInt32(mydata["id"]) };
}
else {
myModel.id = JsonConvert.DeserializeObject<List<int>>(mydata["id"].ToString());
}
result:

insert json file data to sql table using sparksql

Im trying to insert json file data to sql table using sparksql
my sample json file example :
{
"id": "value_string",
"aggregate_id": "value_string",
"type": "value_string",
"timestamp": "value_string",
"data": {
"customer_id": "value_string",
"name": "value_string"
}
}
want to insert in sql table using spark , tried creating like this as shown but couldn't
public class DataOfPerson
{
public string name { get; set; }
public string birthdate { get; set; }
public string customer_id { get; set; }
}
public class Person
{
public string id { get; set; }
public string aggregate_id { get; set; }
public string type { get; set; }
public string timestamp { get; set; }
public List<DataOfPerson> dataOfPerson { get; set; }
}
public class RootObject
{
public Person person { get; set; }
}
var root = JsonConvert.DeserializeObject<RootObject> (sqlContext.read.json(s"abfss://abc#xyz/events.json")
def flattenDataFrame(spark: SparkSession, nestedDf: DataFrame): DataFrame = {
var flatCols = Array.empty[String]
var nestedCols = Array.empty[String]
var flatDF = spark.emptyDataFrame
for (w <- nestedDf.dtypes) {
if (w._2.contains("Struct")) {
nestedCols = nestedCols.:+(w._1)
} else {
flatCols = flatCols.:+(w._1)
}
}
var nestedCol = Array.empty[String]
for (nc <- nestedCols) {
for (c <- nestedDf.select(nc + ".*").columns) {
nestedCol = nestedCol.:+(nc + "." + c)
}
}
val allColumns = flatCols ++ nestedCol
val colNames = allColumns.map(name => col(name))
nestedDf.select(colNames: _*)
}

Asp.net Core does not serialize my new type

Am using .net core +angular 5, and trying to return a list, but one field is null in JSON response. Am using Postman to trigger debugging and saw in VS that the field has a value coming from the DB.
Don't know why it doesn't in the JSON response.
[HttpGet("[action]")]
public IEnumerable<HikingTrail> HikingTrails()
{
var dbOptions = new DbContextOptionsBuilder<HikingTrailContext>();
dbOptions.UseSqlServer("Server = (localdb)\\mssqllocaldb; Database = HikingApp");
var dbContext = new DAO.HikingTrailContext(dbOptions.Options);
return dbContext.HikingTrails.ToList();
}
This returns:
I'm interested in the "mountainRange" field not being null. In debug window it has the right value.
{
"url": null,
"hikingTrailId": 159,
"mountainRange": null,
"name": "My custom name",
"startPoint": null,
"endPoint": null,
"trailCheckpoints": null,
"type": 2,
"dificulty": null,
"duration": "2 1/2 - 3 h",
"minDuration": "00:00:00",
"maxDuration": "00:00:00",
"seasonality": "mediu",
"equipmentLevel": null,
"trailMarking": null,
"hasTrailType": false
},
I was thinking maybe it's EF Core, and have made this 2nd try (i.e. added Include() to dbContext query):
[HttpGet("[action]")]
public IEnumerable<HikingTrail> HikingTrails()
{
var dbOptions = new DbContextOptionsBuilder<HikingTrailContext>();
dbOptions.UseSqlServer("Server = (localdb)\\mssqllocaldb; Database = HikingApp");
var dbContext = new DAO.HikingTrailContext(dbOptions.Options);
return dbContext.HikingTrails.Include( x => x.MountainRange).ToList();
}
Could not get any response in Postman.
EDIT:
public class HikingTrailContext : DbContext
{
public HikingTrailContext(DbContextOptions<HikingTrailContext> options) : base(options)
{
}
public HikingTrailContext():base(){
}
public DbSet<HikingTrail> HikingTrails { get; set; }
public DbSet<MountainRange> MountainRanges { get; set; }
public DbSet<TrailScrapingSessionInfo> TrailScrapingHistory { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
public class HikingTrail
{
[Key]
public int HikingTrailId { get; set; }
public HikingTrail() { }
public MountainRange MountainRange { get; set; }
public String Name { get; set; }
public Location StartPoint { get; set; }
public Location EndPoint { get; set; }
public List<Location> TrailCheckpoints { get; }
public TrailType Type => TrailType.Undetermined;
public String Dificulty { get; set; }
public String Duration { get; set; }
public TimeSpan MinDuration { get; set; }
public TimeSpan MaxDuration { get; set; }
public String Seasonality { get; set; }
public String EquipmentLevel { get; set; }
public String TrailMarking { get; set; }
public String URL;
public bool HasTrailType
{
get
{
return this.Type != TrailType.Undetermined;
}
}
public override bool Equals(object obj)
{
return (((HikingTrail)obj).Name == this.Name);
}
public override int GetHashCode()
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + Name.GetHashCode();
hash = hash * 23 + Type.GetHashCode();
hash = hash * 23 + StartPoint.GetHashCode();
return hash;
}
public override string ToString()
{
return Name.ToString();
}
}
EDIT :
I profiled the db on dbContext.HikingTrails.Include(x => x.MountainRange).Where(x => x.MountainRange != null).ToList(); and the generated query is OK, meaning it has a Name column for MountainRange as well.
P.S.: several fields are null, but those ones don't have data yet.
found one solution, Projection to an anonymous type. Also had to be careful not to have two fields with the same name of "Name"
[HttpGet("[action]")]
public dynamic HikingTrails3()
{
var dbOptions = new DbContextOptionsBuilder<HikingTrailContext>();
dbOptions.UseSqlServer("Server = (localdb)\\mssqllocaldb; Database = HikingApp");
var dbContext = new DAO.HikingTrailContext(dbOptions.Options);
var trails = dbContext.HikingTrails.Include(x => x.MountainRange).
Select( i =>new { Name= i.Name, MountainRangeName = i.MountainRange.Name, i.Duration,
i.Dificulty,i.EquipmentLevel, i.Seasonality, i.Type }).ToList();
return trails;
}

set mandatory string datamember in wcf

I want to set string DataMember as mandatory, I have set "IsRequired = true" but it is showing as optional in XML request.
[MessageContract(WrapperName = "tourinforequest")]
public class TourInfoRequest
{
public TourInfoRequest()
{
Request = new TourInfoRequestRequestData();
}
[MessageBodyMember]
public TourInfoRequestRequestData Request;
}
public class TourInfoRequestRequestData : BaseRequest
{
[DataMember(Order = 1, IsRequired = true ), XmlElement(ElementName = "tourcode")]
public string TourCode { get; set; }
[DataMember(Order = 2, IsRequired = true), XmlElement(ElementName = "depdate")]
public DateTime DepartureDate { get; set; }
}

Problem retrieving results from an index in an embedded RavenDB

I have an index that works great when I query it using the .Net client API with a server based RavenDb.
However, if I change the RavenDb to an embedded type then I cannot query the index directly unless I first query the document that the index uses.
For instance if I have the following document objects which reside as separate collections in the RavenDb:
private class TestParentDocument
{
public string Id { get { return GetType().Name + "/" + AggregateRootId; } }
public Guid AggregateRootId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
private class TestChildProductFlagDocument
{
public string TestParentDocumentId { get; set; }
public short ProductFlagTypeId { get; set; }
}
Then I have the following object which represents the output document that the index maps to:
private class TestJoinIndexOutput
{
public string TestParentDocumentId { get; set; }
public string Name { get; set; }
public short ProductFlagTypeId { get; set; }
}
Here is the index definition:
private class TestJoinIndex : AbstractIndexCreationTask<TestChildProductFlagDocument, TestJoinIndexOutput>
{
public TestJoinIndex()
{
Map = docs => from doc in docs
select new
{
TestParentDocumentId = doc.TestParentDocumentId,
ProductFlagTypeId = doc.ProductFlagTypeId
};
TransformResults = (database, results) =>
from result in results
let parentDoc = database.Load<TestParentDocument>(result.TestParentDocumentId)
select new
{
TestParentDocumentId = result.TestParentDocumentId,
ProductFlagTypeId = result.ProductFlagTypeId,
Name = parentDoc.Name
};
}
My code to call the index looks like so:
var theJoinIndexes = ravenSession.Query<TestJoinIndexOutput, TestJoinIndex>().ToList();
This returns almost immediately and fails unless I do the following:
var theParentDocuments = ravenSession.Query<TestParentDocument>().ToList();
var theJoinIndexes = ravenSession.Query<TestJoinIndexOutput, TestJoinIndex>().ToList();
My Ravendb embedded definition looks like so:
docStore = new EmbeddableDocumentStore
{
UseEmbeddedHttpServer = false,
RunInMemory = true
};
docStore.Configuration.Port = 7777;
docStore.Initialize();
IndexCreation.CreateIndexes(typeof(TestJoinIndex).Assembly, docstore);
You aren't waiting for indexing to complete, call WaitForNonStaleResultsAsOfNow