I'm trying to create a large object whose values are limited to only 3 types: Texture, Geometry, Script
My object would look something like this:
var assets: Assets = {
sky: <Texture>,
ground: <Texture>,
city: <Geometry>,
people: <Script>,
cars: <Script>,
sun: <Circle> // <--This should fail because it's not one of the 3 types
//...
}
How can I declare the Assets interface so the value in each key-value pair is limited to these 3 types? I tried starting with:
interface Assets{
key: Texture | Geometry | Script;
}
but then it breaks when I assign
this.assets = {sky: new Texture()}
Because it's expecting only key instead of sky. Is there any way of achieving this without nesting objects within objects?
How about:
type Assets = {
[key: string]: Texture | Geometry | Script;
}
That type will allow for string keys and values of one of the types you requested.
More on the subject: Indexable Types
Related
Cannot create Dynamic Scenario Outline via Java call in Karate.
I can create a Dynamic Scenario Outline with "hard-coded" Json Array for example:
* def foobar = [{ 'type': 'app' }]
But when I attempt to generate the same Json Array from a Java class, I always get the following Karate warning(s) and the Dynamic Scenario Outline never executes:
WARN com.intuit.karate - ignoring dynamic expression, did not evaluate to list
-- OR --
WARN com.intuit.karate - ignoring dynamic expression list item 0, not map-like
I've tried using the Karate key-words 'def', 'string', 'json' as the var type but no luck. I've even tried hard-coding the same string shown above in the Java method with no luck.
I declare/call my Java class in 'Background:' and print what is given back and it "looks" correct.
Background:
* def IdaDataApiUtil = Java.type('data.IdaDataApiUtil')
* def foobar = IdaDataApiUtil.getClientExample('ida-sp')
* print foobar
I then try to utilize the JsonArray in my 'Example:' like such:
Examples:
| foobar |
At this point I get the above mentioned error(s), depending on what I've tried to return (JsonArray, JsonObject, Map, List).
If I simply use the hard-coded 'def':
* def foobar = [{ 'type': 'app' }]
It works as expected.
In my Java code I've tried various things:
Hard-coded Json string:
public static String getClientExample() {
return "[{ 'type': 'app' }]";
}
List:
public static List<String> getClientExample() {
List<String> list = new ArrayList<>();
list.add("'type': 'app'");
return list
}
Map:
public static Map<String, Object> getClientExample() {
Map<String, Object> map = new HashMap<>();
map.put("type", "app");
return map;
}
I've played with variations of key/values in both list/map with no luck. I've also tried with JSONObject/JSONArray but no luck there as well.
I feel like I'm missing something vary obvious but I can't see the forest through the trees at the moment...
I attempt to generate the same Json Array from a Java class,
What you return from the Java code should be a List<Map<String, Object>> and it should work fine. You have tried List<String> and that is the problem.
Read this section of the docs: https://github.com/intuit/karate#type-conversion
Another tip, you can try a "cast" to ensure it is in the JSON array form you need, so if you are too lazy to form properly nested Map-s, just return a raw JSON string from Java, and the below line will convert it correctly.
* json foobar = foobar
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.
I'm just starting to explorer GraphQL as an option for my analytic platform API layer.
My UI is mainly built from tables and charts. most of the times the data represents some DB columns grouped by a dimension.
I've found the following article https://www.microsoft.com/developerblog/2017/09/28/data-independent-graphql-using-view-model-based-schemas/ from Microsoft, describing their take on how suck GraphQL schemas should be designed (see below).
type Query {
channels(source: String!, query:String!, appId:String!, apiKey:String!): [Channel]
lineCharts(source: String!, query:String!, appId:String!, apiKey:String!, filterKey:String, filterValues:[String]): [LineChart]
pieCharts(source: String!, query:String!, appId:String!, apiKey:String!): [PieChart]
barCharts(source: String!, query:String!, appId:String!, apiKey:String!, filterKey:String, filterValues:[String]): [BarChart]
}
type Channel {
name: String
id: Int
}
type LineChart {
id: String
seriesData : [Series]
}
type PieChart {
id: String
labels: [String]
values: [Int]
}
type BarChart {
id: String
seriesData : [Series]
}
type Series {
label: String
x_values: [String]
y_values: [Int]
}
It seems to me that this design is strict, forcing any new chart to be added to the root Query. How can the schema be more generic, without loosing GraphQL benefits?
You could do something with union types and inline/fragments
union Chart = LineChart | PieChart | BarChart
type Query {
charts(
source: String!
query: String!
appId: String!
apiKey: String!
filterKey: String
filterValues: [String]
): [Chart]
}
Then you can have your charts resolver bring ALL the charts and write your queries like
fragment Identifiers on Chart {
__typename
id
}
query {
charts(...) {
...on LineChart {
...Identifiers
seriesData
}
...on PieChart {
...Identifiers
labels
values
}
...on BarChart {
...Identifiers
seriesData
}
}
}
The Identifiers will provide you with some information about what type you're dealing with and it's id, but you can extend it to whatever you like as long as those fields are common to all types on that union (or you can spread it only on some of the types).
There are 2 ways you can go about if you don't want to bring in all the charts:
Add inline fragments for only the types you want, but the rest will still be there, in the form of empty objects.
Pass another argument to the resolver representing the type/s you want
P.S. You can get as granular as you like, there are also interfaces and input types.
How should I proceed when I want to generate table from list of lists which contains only strings(ex. data from csv). Names of columns don't matter. From all examples provided I saw only binding table items to specific model(which doesn't fit there as I have unknown number and names of columns).
If you already know the column names and data type, I would suggest to hard code that. If you know nothing about the format and simply want to create a TableView with completely dynamic columns, you can use the index in the csv data as an extractor to create StringProperty values for your data:
class MyView : View() {
val data = FXCollections.observableArrayList<List<String>>()
val csvController: CsvController by inject()
init {
runAsync {
csvController.loadData()
} ui { entries ->
// Generate columns based on the first row
entries.first().forEachIndexed { colIndex, name ->
root.column(name, String::class) {
value { row ->
SimpleStringProperty(row.value[colIndex])
}
}
}
// Assign the extracted entries to our list, skip first row
data.setAll(entries.drop(1))
}
}
override val root = tableview(data)
}
class CsvController : Controller() {
// Load data from CSV file here, we'll use som static data
// where the first row is the headers
fun loadData() = listOf(
listOf("Name", "Age"),
listOf("John", "42"),
listOf("Jane", "24")
)
}
This approach would only be good for visualizing the data in a CSV file. If you need to edit or manipulate the data, knowledge of the data types up front would yield a less flimsy application IMO :)
I'm using ColdFusion, but I'd be interested to know how other languages cope with this.
Is there a better way of returning all of an objects variables (getters) without writing a massive toString() method on the object.
variables.oCity = createObject("component", "_lbr._core._locations.city").init();
variables.oCity.setName(request.parameters.sCityName);
variables.oCity.setCountryID(request.parameters.nLocationCountryID);
if(request.parameters.nStateID eq 0){
variables.stArgs = {};
variables.stArgs.sState = request.parameters.sLocationCountry;
variables.stArgs.nCheckCountryID = request.parameters.nCountryID;
variables.oCity.setStateID = application.stObj.oLocationBusiness.getState(argumentCollection=variables.stArgs).getStateID();
} else {
variables.oCity.setStateID = request.parameters.nStateID;
}
My code looks like that. What I'd like is to output everything I have just set (as well as anything that the object defaults too) without writing a giant toString that concatenates all the various variables that might look like this:
Object: StateID = 12, Name = "Argentina", CountryID = 32, CityID = 44
My heart tells me this is unlikely.
This depends on how you are storing your variables within your object. I generally store all of my variables in a variables.instance structure. I then create a get() that simply returns the variables.instance structure:
public struct function get(){
return Duplicate(variables.instance);
}
If you use cfproperty, and accessor=true or persistent=true in CF9+, a dump of the cfc will return all the properties without getter=false.