I have an array in a NotationConstant class:
export class NotationConstant {
public static readonly TIME_SIGNATURES: Array<number> = [2, 4];
}
Then I use it in another SettingsDialogComponent class:
private instantiateLists(): void {
NotationConstant.TIME_SIGNATURES.forEach((timeSignature: number) => {
console.log(timeSignature);
this.timeSignatures.push({ 'id': timeSignature, 'name': String(timeSignature) });
});
}
The console log statement show:
{id: 2, name: "2"}
{id: 4, name: "4"}
Where do these id property and name property come from ?
Another stranger thing.
I add the array definition in the SettingsDialogComponent class:
public static readonly TIME_SIGNATURES: Array<number> = [2, 4];
private instantiateLists(): void {
SettingsDialogComponent.TIME_SIGNATURES.forEach((timeSignature: number) => {
console.log(timeSignature);
this.timeSignatures.push({ 'id': timeSignature, 'name': String(timeSignature) });
});
}
Now the console log statement shows:
2
4
Why moving the array definition into another class changes its traversing ?
UPDATE: The issue is gone. The above source code is exactly the same. High chaparral.
I have a array of jsons that I want to parse to my class Tournament.
The class Tournament looks like this:
export class Tournament { constructor (public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
){ }
}
The class Team looks like this:
export class Team { constructor (public id: number,
public name: string,
public rank: number,
public occupied: boolean,
public group: string
){ }
}
And the JSON that i receive looks like this:
[{"id":1,
"name":"Schulcup1",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":83,"dayOfWeek":"FRIDAY","leapYear":false,"dayOfMonth":24,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":1,"name":"Team1","rank":8,"occupied":false,"group":"A"},
{"id":2,"name":"Team2","rank":1,"occupied":false,"group":"A"},
{"id":3,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":4,"name":"Team4","rank":16,"occupied":false,"group":"A"},
{"id":5,"name":"Team5","rank":2,"occupied":false,"group":"B"},
{"id":6,"name":"Team6","rank":16,"occupied":false,"group":"B"},
{"id":7,"name":"Team7","rank":8,"occupied":false,"group":"B"},
{"id":8,"name":"Team8","rank":4,"occupied":false,"group":"B"}],
"active":true},
{"id":2,
"name":"Schulcup2",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":82,"dayOfWeek":"THURSDAY","leapYear":false,"dayOfMonth":23,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":48,"name":"Team1","rank":16,"occupied":false,"group":"A"},
{"id":49,"name":"Team2","rank":2,"occupied":false,"group":"A"},
{"id":50,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":51,"name":"Team4","rank":1,"occupied":false,"group":"A"},
{"id":52,"name":"Team5","rank":16,"occupied":false,"group":"B"},
{"id":53,"name":"Team6","rank":8,"occupied":false,"group":"B"},
{"id":54,"name":"Team7","rank":16,"occupied":false,"group":"B"},
{"id":55,"name":"Team8","rank":16,"occupied":false,"group":"B"}],
"active":true}]
If I try to parse the JSON with JSON.parse() I get an error that there is an unexpected token in JSON at position 0 most likely because of the [ since it is an array of JSON but how can I iterate through it?
And also how can I iterate through the teams in the JSON to create an array of teams?
It is already parsed. Just use it as an object!
No need to use classes here, simply cast your JSON to interfaces, if you really do not need classes. Casting to interfaces is easy and painless ;) And no need of using JSON.parse here.
So use interfaces if you can, here is Tournament:
export interface Tournament {
public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
}
Service:
getTournaments(): Observable<Tournament[]> {
return this.http.get('src/data.json')
.map(res => res.json() as Tournament[])
}
TS:
tournaments: Tournament[] = [];
getTournaments() {
this.service.getTournaments()
.subscribe(data => {
this.tournaments = data;
})
}
DEMO
I have an structure like this:
{
_id: 123,
bs: [
{
_id: 234,
cs: [
{
_id: 456,
ds : [
{
_id: 678,
emails[
"email#gmail.com"
]
}
]
}
]
}
]
}
My classes in Morphia seems like this
#Entity
public class A {
#Id
private ObjectId id;
#Embedded
private List<B> bs;
}
public class B {
private ObjectId id;
#Embedded
private List<C> cs;
}
public class C {
private ObjectId id;
#Embedded
private List<D> ds;
}
public class D {
private ObjectId id;
#Embedded
private List<String> emails;
}
What I am trying to do is insert an email inside embedded array with Morphia without retrieve all element A and use updateFirst.
This is the query I am trying execute
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.criteria("bs.cs.id").equal(new ObjectId(cID));
query.criteria("bs.cs.ds.id").equal(dID);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.$.emails", email);
this.basicDAO.update(query, updateOps);
I also read about this post Update an item in an array that is in an array with said that
$ operator does not work "with queries that traverse nested arrays".
So I tried something like:
D d = new D(dID);
C c = new C(new ObjectId(cID));
Query<Event> query = this.basicDAO.createQuery();
query.criteria(Mapper.ID_KEY).equal(new ObjectId(aID));
query.field("bs.cs").hasThisElement(c);
query.field("bs.cs.ds").hasThisElement(d);
UpdateOperations<Event> updateOps = this.basicDAO.createUpdateOperations().set("bs.cs.ds.emails", email);
this.basicDAO.update(query, updateOps);
However it still doesn't work. Any idea how solve this? The error message that I receive is cannot use the part ... to transverse the element
Based on your stand-in use case, I think you should "invert" your schema. Each document will represent a lecture and will be tagged with its theme, edition, and event:
{
"_id" : ObjectId("54da1ff0a9ce603a239c3075"),
"event" : "X0004",
"edition" : "A0002,
"theme" : "RT0005",
"votes" : 22
}
event, edition, and theme can be some kind of identifiers, and might be references to event, edition, and theme documents in other collections. To cast a vote for a particular lecture, just update it by _id:
db.test.update({ "_id" : ObjectId("54da1ff0a9ce603a239c3075") }, { "$inc" : { "votes" : 1 } })
While I don't know your full requirements, I think this is a better basic design given your example use case.
I have a JSON string. which has a part like this
"Result": {
"AdditionalInfo": {
"SubCategoryID": "978",
"SellerPartNumber": "04-VO7T-14PP",
"ManufacturerPartNumberOrISBN": "04-VO7T-14PP",
"UPC": null
},
"ErrorList": {
"ErrorDescription": [
{
"#cdata-section": "Error(s). Item not created."
},
{
"#cdata-section": "Error:[Item does not exist. Please create a new list.]"
}
]
}
}
However, sometimes that part is an array as well.
like
"Result": [
{
"AdditionalInfo": {
"SubCategoryID": "1512",
"SellerPartNumber": "TY-SZT1-358V",
"ManufacturerPartNumberOrISBN": "TY-SZT1-358V",
"UPC": null
},
"ErrorList": {
"ErrorDescription": [
{
"cdata-section": "Error(s). Item not created."
},
{
"cdata-section": "CufflinkMaterial - Property: [CufflinkMaterial] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
},
{
"cdata-section": "CufflinkType - Property: [CufflinkType] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
}
]
}
},
{
"AdditionalInfo": {
"SubCategoryID": "1512",
"SellerPartNumber": "UF-T05C-T6XG",
"ManufacturerPartNumberOrISBN": "UF-T05C-T6XG",
"UPC": null
},
"ErrorList": {
"ErrorDescription": [
{
"cdata-section": "Error(s). Item not created."
},
{
"cdata-section": "CufflinkMaterial - Property: [CufflinkMaterial] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
},
{
"cdata-section": "CufflinkType - Property: [CufflinkType] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
}
]
}
},
{
"AdditionalInfo": {
"SubCategoryID": "1512",
"SellerPartNumber": "5B-1137-WT3O",
"ManufacturerPartNumberOrISBN": "5B-1137-WT3O",
"UPC": null
},
"ErrorList": {
"ErrorDescription": [
{
"cdata-section": "Error(s). Item not created."
},
{
"cdata-section": "CufflinkMaterial - Property: [CufflinkMaterial] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
},
{
"cdata-section": "CufflinkType - Property: [CufflinkType] value error. The submitted value: [MPS.Domain.SubCategoryProperty] is not recognized for this property."
}
]
}
}
]
Is there a generic way that I can Deserlize both JSON without defining different objects? So like, I define an array of Result object, and when there is single entity, it will create one index in the object array, and when there are multiple, it may create multiple indexes in the array.
Ultimate goal is to use object object and use that to parse both single Result object or multiple.
Is that something possible?
thanks
Sameers
Thanks Brian Rogers
The answer was in your link.
How to handle both a single item and an array for the same property using JSON.net
I converted that to VB.NET using this code.
Class SingleOrArrayConverter(Of T)
Inherits Newtonsoft.Json.JsonConverter
Public Overrides Function CanConvert(ByVal objectType As Type) As Boolean
'Return (objectType = GetType(List(Of T)))
Return objectType.Equals(GetType(Generic.List(Of T)))
End Function
Public Overrides Function ReadJson(ByVal reader As Newtonsoft.Json.JsonReader, ByVal objectType As Type, ByVal existingValue As Object, ByVal serializer As Newtonsoft.Json.JsonSerializer) As Object
Dim token As Newtonsoft.Json.Linq.JToken = Newtonsoft.Json.Linq.JToken.Load(reader)
If token.Type = Newtonsoft.Json.Linq.JTokenType.Array Then
Return token.ToObject(Of Generic.List(Of T))()
End If
Dim list As New Generic.List(Of T)
list.Add(token.ToObject(Of T)())
Return list
End Function
Public Overrides ReadOnly Property CanWrite() As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub WriteJson(ByVal writer As Newtonsoft.Json.JsonWriter, ByVal value As Object, ByVal serializer As Newtonsoft.Json.JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class
and applied this attribute to my data definition.
<Newtonsoft.Json.JsonProperty("Result")> _
<Newtonsoft.Json.JsonConverter(GetType(Utilities.JSONUtilities.SingleOrArrayConverter(Of FeedResultType)))> _
Public Property Result() As Generic.List(Of FeedResultType)
Get
Return m_Result
End Get
Set(ByVal value As Generic.List(Of FeedResultType))
m_Result = value
End Set
End Property
and its all good now.
thanks
Sameers
Yes, I was using NewtonSoft library
i have the following json:
{
"Header": {
"MCC": "415",
"FO": "0",
"REGID": "5"
},
"Contacts": [
{
"NAME": "jocelyne",
"MO": "70123456"
},
{
"NAME": "eliane",
"MO": "03123456"
}
] }
and i'm parsing the json string into a datatable using this method:
object classes:
Public Class Data
Public Header As Header
Public Contacts As DataTable
End Class
<System.Runtime.Serialization.DataContract()>
Public Class Header
<System.Runtime.Serialization.DataMember(Name:="MCC")>
Public MCC As Integer
<System.Runtime.Serialization.DataMember(Name:="FO")>
Public FO As Integer
<System.Runtime.Serialization.DataMember(Name:="REGID")>
Public RegId As Integer
End Class
.net functions:
Dim data As New Data
data = JsonConvert.DeserializeObject(Of Data)(json)
mcc = data.Header.MCC
FO = data.Header.FO
regid = data.Header.RegId
contactsDT = data.Contacts
my problem is that the contacts array in the json is being parsed as a datatable in the same order as passed in the json... is there a way to change the order of the columns? what i mean is that if i got in the json let's say mo before name i need to get in the datatable name before mo all the time
is there a way to do that?