If I define a moddle file with bpmn-js like this
{
name: "thisArgument",
superClass: [
"Element"
],
properties: []
},
{
name: "myData",
superClass: [
"Element"
],
properties: [
{
name: "argument",
type: "thisArgument"
}
]
},
Then the resulting XML (when I call saveXML) will have an element called thisArgument, despite the fact that the name is "argument". First, is that a bug? If not, how do I control the output so that the XML contains argument rather than thisArgument? I've searched the docs and examples but can't find how to do this.
The only workaround I found was to make it type: "argument" and then define argument with a superClass of thisArgument and no extra properties (essentially making an alias). However, that only works if all instances of argument are identical. Eg. if the XML needed to be
<A><argument/></A>
<B><argument/></B>
where the argument in A has a different shape than the argument in B, then there would be a conflict since I can't define argument twice.
I can sort of answer my own question. I found this serialize option and experimented, and it mostly does what I want, but sometimes it adds an unwanted xsi:type="originalType" attribute and sometimes it doesn't. Maybe it depends on isBody but I'm not sure. If anyone knows the details of how it works, please reply.
properties: [
{
name: "argument",
type: "thisArgument",
xml: {
serialize: "xsi:type"
},
}
]
The closest thing I found to documentation on it is https://forum.bpmn.io/t/bpmn-json-documentation/1304 which describes it as "additional meta-data impecting XML serialization of a type", so I'd appreciate any extra details anyone can supply.
Update:
The docs don't mention this, but it turns out that serialize: "property" is exactly what I need. This does the same as serialize: "xsi:type" but doesn't add the xsi:type attribute.
xml: {
serialize: "property"
},
I found this by hunting the code in one of the related packages, moddle-xml.
In write.js, there's code that looks for the xsi:type or property entry:
// allow serialization via type
// rather than element name
var asType = serializeAsType(p),
asProperty = serializeAsProperty(p);
In the same file, I found some code that appears to explain why the xsi:type didn't always show up, too:
// only serialize xsi:type if necessary
if (descriptor.name === this.propertyDescriptor.type) {
return attributes;
}
Related
I have this json:
{
"$type": "System.Collections.Generic.List<MyType>",
"$values": [
{
"$type": "MyType",
"o": 7.54,
"t": 1619002800000,
"n": 3
},
{
"$type": "MyType",
"o": 7.53,
"t": 1619005140000,
"n": 3
}
]
}
I want to deserialize it back into a List<MyType>. I thought there would be an easy way to do that some thing like this:
var myList = json.FromJson<MyType>();
but that doesn't work.
I have figured out a way to accomplish my goal but it's a bit messy so I was wondering if there's a better way that I'm not aware of. Here's the messy way I came up with:
var myListOfObject = (List<object>)((Dictionary<string, object>)JSON.parse(json))["$values"];
var myTypes = myListOfObject.ConvertAll(x => JSON.stringify(x).FromJson<MyType>());
I'm not necessarily looking for fewer lines of code because 2 isn't anything to complain about. I'm just hoping there is a way that doesn't require all the casting and parsing and rather can accept the json as is and get it back to the type it came from. Maybe there's even a parameter I can set to tell it to validate types during the deserialization since the full type names are in the json.
You should use the same serializer you used to serialize the payload to deserialize it. ServiceStack.Text uses __type to embed its type information, in a different schema so you wont be able to use ServiceStack.Text to automatically deserialize it into the embedded type.
This likely used JSON.NET which you should use instead to deserialize it, otherwise yeah you can use ServiceStack's JS Utils to deserialize arbitrary JSON as you're doing.
I'm going through the docs to try and figure out how loops work so I can validate every object of an array of objects match the schema.
It seems like recursion is what I want but the example given doesn't work: https://json-schema.org/understanding-json-schema/structuring.html
I'm trying to validate that example but its always "valid". I tried changing all the field names in the JSON and it doesn't matter:
Not sure what's happening. For this example how would I validate every child matches the person schema (without statically writing out each one in the schema).
For example, I want to valid this JSON. there could be any number of objects under toplevel and any number of objects under "objectsList". I want to make sure every object under "objectsList" has the right field names and types (again without hard coding the entire thing in the schema):
{
"toplevel": {
"objectOne": {
"objectsList": [
{
"field1": 1231,
"field2": "sekfjlskjflsdf",
"field3": ["ssss","eeee"],
},
{
"field1": 11,
"field2": "sef",
"field3": ["eeee","qqqq"],
},
{
"field1": 1231,
"field2": "wwwww",
"field3": ["sisjflkssss","esdfsdeee"],
},
]
},
"objectTwo": {
"objectsList": [
{
"field1": 99999,
"field2": "yuyuyuyuyu",
"field3": ["ssssuuu","eeeeeee"],
},
{
"field1": 221,
"field2": "vesdlkfjssef",
"field3": ["ewerweeee","ddddq"],
},
]
},
}
}
What's wrong?
The problem here is not the recursion – your schema looks good.
The underlying issue is the same as here: https://stackoverflow.com/a/61038256/5127499
JSON Schema is designed for extensibility. That means it allows any kind of additional properties to be added as long as they are not conflicting with the known/expected keywords.
Solution
The solution here is to add "additionalProperties": false in your "person" (from the screenshot) and top-level schema to prevent those incorrect objects to be accepted. Same goes for your second example: in any definitions of "type": "object" you'd have to add "additionalProperties": false if you don't want to allow these extraneous properties to be defined.
Alternatively, you can declare your expected properties as required to ensure that at least those are present.
Why?
As per json-schema.org/understanding-json-schema (emphasis mine):
The additionalProperties keyword is used to control the handling of extra stuff, that is, properties whose names are not listed in the properties keyword. By default any additional properties are allowed.
The additionalProperties keyword may be either a boolean or an object. If additionalProperties is a boolean and set to false, no additional properties will be allowed.
To address the screenshot you posted and why the instance passes:
The schema is looking to find a person property, but that property doesn't exist.
The schema does not declare that person is required.
The schema does not declare requirements on undefined properties, so it will always accept the personsdfsd property with whatever value is in it, without checking it further.
So in short, your JSON data is bad and your schema doesn't have any protections against that.
Other than that, your schema looks good. It should validate that items in the children property match the person definition's subschema.
i am parsing json and what i get set of dictionary but after parsing it will automatically change it order. i just need same order as same i am getting from json parsing.
NOTE: i want to make one functionality which depends on dictionary order, i don't want to make it manually. so it will not need to make it every-time to do.it will help to change dynamically in future
Example:
From Json:
Section:
{
category:{},
location:{},
vehicle_type:{},
mode_type:{}
}
after convert into NSDicationary:
Section:
{
vehicle_type:{}
category:{},
location:{},
mode_type:{}
}
Thanks
Order of key:value doesn't matter for JSON, as you can directly access value with the help of key string. An dictionary does not support indexing of elements, so you can't.
Dictionaries are not ordered collections. On other hand, arrays are.
Note, if you don't have access over the json format, you got no guarantees about the order of elements, if you don't have hardcoded logic in your app.
Having said that, let's take a deeper look into your case. It happens that you have one main object in your json that is Section. What is more, you have 4 ordered properties of this object that are of specific kind of their own: 0: category; 1: location; 2: vehicle_type; 3: mode_type. So here comes the good part: just change your json to look something like this:
Section:
[
{
title: "category",
value: {}
},
{
title: "location",
value: {}
},
{
title: "vehicle_type",
value: {}
},
{
title: "mode_type",
value: {}
}
]
Having this json, you just go through the Section ordered elements, check the title of the element, and create the corresponding Object. This way you can achieve what you are after.
.NET 4.0; VS 2010.
We're consuming a web service that does not offer a WSDL. The data that is returned is not particularly complicated so we thought we would work with dynamic/anonymous types. Here is an example of the JSON returned from one of the service methods (this string has been verified with JSONLint):
[
{
"value": "AAA"
},
{
"value": "BBB"
},
{
"value": "CCC"
},
{
"value": "DDD"
},
{
"value": "EEE"
},
{
"value": "FFF"
}
]
Tried using:
dynamic respDyn = JsonConvert.DeserializeObject(jsonStringAbove);
In this case, no errors are thrown, but in trying to access the resp variable, the Visual Studio debugger reports "The name 'resp' does not exist in the current context".
Tried LINQ next:
var respLinq = JObject.Parse(jsonStringAbove);
Which results in a runtime error: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
Found this article that recommended different parsing methods depending on the format of the JSON:
if (jsonStringAbove.StartsWith("["))
{
var arr = JArray.Parse(jsonStringAbove);
}
else
{
var obj = JObject.Parse(jsonStringAbove);
}
When var arr = JArray.Parse(jsonStringAbove); is hit, the debugger simply exists the method and returns to the calling procedure. No error is thrown. If the leading and trailing square brackets are removed, another run time error similar to the results in the second example is encountered.
So. Not sure where to turn at this point. Seems like what we're trying to do is very straightforward which make me think I'm missing something blatantly obvious.
Not sure why, but the solution to this was to declare my variables as fields within the class. Variables that were local to the methods I was working with simply did not work. Once declared as class-wide variables, the code behaved as expected. Very odd. I suspect that this problem may be specific to my VS environment and/or solution configuration as it does not appear to be occurring with anyone else. Lucky me.
I see that the restkit document is quite nice and has variety of examples on object modelling. There is also an example of nested mapping but I find my scenario little bit different than this. RestKit documentation provides the example mapping of the nested attribute with the following json format.
Sample JSON structure from the RestKit Documentation :
{
"blake": {
"email": "blake#restkit.org",
"favorite_animal": "Monkey"
},
"sarah": {
"email": "sarah#restkit.org",
"favorite_animal": "Cat"
}
}
Suppose that my json is a bit different as this;
My JSON structure :
{
"id" : 1,
"author" : "RestKit",
"blake": {
"email": "blake#restkit.org",
"favorite_animal": "Monkey"
},
"sarah": {
"email": "sarah#restkit.org",
"favorite_animal": "Cat"
}
}
I created two different managedobject model with the following attributes and to many relations.
Two different entities for my structure Product and creator to map the above JSON object.
Product Creator
identifier <------------------- >> name
author email
favouriteAnimal
Now, my mapping would look like this for Product model would be;
This is how I map the Product entity,
[mapping mapKeyPath:"id" toAttribute:"identifier"];
[mapping mapKeyPath:"author" toAttribute: "author"];
But note here, mapping the nested dictionary attribute does not work for me.
// [mapping mapKeyOfNestedDictionaryToAttribute:#"creators"];
Now, in the authors class.
I could not figure out the usual way to map the above JSON structure.
If you have control over the web service, I would strongly recommend reorganizing your response data like this:
{
product:
{
id: 1,
author: 'RestKit',
creators: [
{
id: 1,
name: 'Blake',
email: '...',
favorite_animal: 'Monkey'
},
{
id: 2,
name: 'Sarah',
email: '...',
favorite_animal: 'Cat'
}
]
}
}
Following this structure, you'd be able to use RestKit's nested mapping features, and the relationship would be correctly reflected in the deserialized objects received by the object loader delegate. RestKit relies on naming and structure standards to simplify the code required to achieve the task. Your example deviates from key-value coding standards, so RK doesn't provide an easy way to interact with your data format.
If you don't have access or you can't change it, I think you'll need to map known key-value pairs with a mapping and perform the remaining assignments with a custom evaluator. You'd need to assume the unknown keys are actually name values for associated creators and their associated values contain the attribute hash for each. Using that, you'd then reconstruct each object manually.