Spray Returning JSON - spray

I've just started using Spray and I'm building a sample API that simply returns some JSON.
Take the following example. I have the alphabet stored in a singleton...
class Alphabet {}
object Alphabet {
final val alphabet = Array('a', 'b', 'c', ...)
}
I then have a simple spray route...
path("list") {
get {
respondWithMediaType(`application/json`) {
complete(Alphabet.alphabet)
}
}
}
This works fine and seems to return an "application/json" response with the correct data. But is this valid? i.e. is this a correctly formatted response that would be expected by an end user?
The reason I ask is I have looked at a number of Spray examples and most seem to use case classes and specify custom JSON formatters similar to this...
object CustomJsonProtocol extends DefaultJsonProtocol {
implicit val responseFormat = jsonFormat3(CaseClassHere)
}
...
complete {
CaseClassHere("Test", "Test");
}
Whats the correct approach?
Thanks

Related

angular 11 display static text to dynamic value

I'm having 2 JSONs. The first one is having the format of the JSON value and the second one is having the actual value which is I want to display in the UI.
But I'm seeing the "application.appID" instead of 101. Does any help please?
Not working if label:"applicaiton.appID". I'm having label: "string"
working if label: applicaiton.appID
component.ts
this.json1={
label:"applicaiton.appID"
};
this.application ={
appID:101
};
ui.html
<mat-label> {{json1.label}} </mat-label>
<mat-label [innterHtml]="json1.lable"> </mat-label>
If I understand right, what you're trying to do is to interpolate based on a string expression coming from a json. This is not something that you can do by just using the {{ }} construct. Here's why:
(For simplicity I will use div instead of mat-label)
In theory, this line would solve your problem
<div>{{this[json1.label]}}</div>
Just that it doesn't work since the inner json1.label part is not expanded/evaluated as expected.
Even if we manually write it as an explicit string, it still doesn't give us 101.
<div>{{this['application.appID']}}</div>
The only way to make such a syntax work would be to chain the field indexers, but that doesn't help us with using json1.label as the 'path' of the object and inner field.
<div>{{this['application']['appID']}}</div> // this returns 101, but it's not helpful for us...
So as you can see, pure html interpolation can't really help us achieve our goal. Instead, we should create a helper method inside the .component.ts file:
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
json1 = {
label: 'application.appID'
};
application = {
appID: 101
};
accessPropertyByString(path: string): any {
let result = this;
const parts = path.split('.');
for (const part of parts) {
if (part in result) {
result = result[part];
} else {
return null;
}
}
return result;
}
}
The new accessPropertyByString() method can be now used in the html template like this:
<div>{{accessPropertyByString(json1.label)}}</div>
Which finally returns 101 as expected.

Multiple types for a single variable (parameter/return type)

I am very new to Dart so excuse me if I didnt see this part.
I want to make a union type e.g. for a function input. In TS this would be:
let variableInput: string | number
typedef doesnt really define types but functions and enums dont really help too.
On the other side how should it look like when a function return either one or the other of two types? There must be something I dont see here.
There are no union types in Dart.
The way to do this in Dart is returning/accepting dynamic as a type:
dynamic stringOrNumber() { ... }
void main() {
final value = stringOrNumber();
if (value is String) {
// Handle a string value.
} else if (value is num) {
// Handle a number.
} else {
throw ArgumentError.value(value);
}
}
See also: https://dart.dev/guides/language/sound-dart

FLUTTER How to get variable based on passed string name?

I have stored variables in a class with their code names.
Suppose I want to get XVG from that class, I want to do
String getIconsURL(String symbol) {
var list = new URLsList();
//symbol = 'XVG'
return list.(symbol);
}
class URLsList{
var XVG = 'some url';
var BTC = 'some url';
}
Can someone help me achieve this or provide me with a better solution?
Dart when used in flutter doesn't support reflection.
If it's text that you want to have directly in your code for some reason, I'd advise using a text replace (using your favourite tool or using intellij's find + replace with regex) to change it into a map, i.e.
final Map<String, String> whee = {
'XVG': 'url 1',
'BTC': 'url 2',
};
Another alternative is saving it as a JSON file in your assets, and then loading it and reading it when the app opens, or even downloading it from a server on first run / when needed (in case the URLs need updating more often than you plan on updating the app). Hardcoding a bunch of data like that isn't necessarily always a good idea.
EDIT: how to use.
final Map<String, String> whee = .....
String getIconsURL(String symbol) {
//symbol = 'XVG'
return whee[symbol];
}
If you define it in a class make sure you set it to static as well so it doesn't make another each time the class is instantiated.
Also, if you want to iterate through them you have the option of using entries, keys, or values - see the Map Class documentation
I'd just implement a getProperty(String name) method or the [] operator like:
class URLsList{
var XVG = 'some url';
var BTC = 'some url';
String get operator [](String key) {
switch(key) {
case 'XVG': return XVG;
case 'BTC': return BTC;
}
}
}
String getIconsURL(String symbol) {
var list = new URLsList();
return list[symbol];
}
You can also use reflectable package that enables you to use reflection-like code by code generation.
Assuming that the class is being created from a JSON Object, you can always use objectName.toJSON() and then use the variable names are array indices to do your computations.

Spray 1.2 ignores content-type header in response

I am trying to set application/json as content-Type in a spray-routing actor. But the content-type i see in my response always is text/plain. I tried using the spray-routing approach ("something") and the spray-can approacch ("something2") but the two routes don't send the response-type properly. Did I miss something?
def receive = runRoute {
path("something") {
get {
respondWithHeader(`Content-Type`(`application/json`)) {
complete("""{ "key": "value" }""")
}
}
} ~
path("something2") {
get {
complete(HttpResponse(entity = """{ "key": "value" }""").withHeaders((List(`Content-Type`(`application/json`)))))
}
}
}`enter code here`
It seems that the responseheader is overwritten by the marshaller for string.
Like this it works like a charm:
path("something") {
get {
respondWithMediaType(`application/json`) {
complete("""{ "key": "value" }""")
}
}
}
Actually, there is a much better approach to return a json with a application/json content type with spray.json module. If you have just key:value pairs it would be much cleaner to use SprayJsonMarshaller, which would authomatically set appropriate header. Consider the following example:
(get & path("somePath")) { complete(Map("key" -> "value")) }
To make a json response you just need to import two things:
import spray.json.DefaultJsonProtocol._ // contains default marshallers
import spray.httpx.SprayJsonSupport._ // will do all the headers work
If you have your own case class which you would like to send over the wire, then provide a converter into json format:
import spray.json.DefaultJsonProtocol._
case class SomeClass(name: String)
object SomeClass {
implicit val someClassJson = jsonFormat1(SomeClass.apply)
}
It's a much better approach cause if you later would like to change the format in you response, all you need to do is to change a marshaller, the rewrite your code.
number in the end of jsonFormat method equals to the number of case class arguments.

Mocking with Dart - How to filter logs when a callsTo argument

I'm wondering if it's possible to filter logs by properties of passed arguments to a specific function. To be more specific, here's where I'm starting:
_dispatcher.getLogs(callsTo("dispatchEvent", new isInstanceOf<PinEvent>()));
I'd like to further filter this by PinEvent.property = "something"
In pseudo-code, I guess it'd look like this:
_dispatcher.getLogs(callsTo("dispatchEvent", new isInstanceOf<PinEvent>("property":"something")));
Any ideas? I know I can loop through the entire log list, but that seems dirty, and I would think there'd be a better way.
Thanks :-)
You can write your own matcher and use it instead of isInstanceOf
or derive from isInstanceOf and extend this matcher with the missing functionality.
I don't know of a matcher that does this out of the box (but I must admit that I didn't yet work very much with them).
While waiting for responses I whipped this up real quick. It's probably not perfect, but it does allow you to combine an isInstanceOf with this matcher using allOf. ex:
allOf(new isInstanceOf<MyThing>(), new ContainsProperty("property", "propertyValue"));
And here's the Matcher:
class ContainsProperty extends Matcher {
final String _name;
final dynamic _value;
const ContainsProperty(String name, dynamic value):this._name = name, this._value = value;
bool matches(obj, Map matchState) {
try {
InstanceMirror objMirror = reflect(obj);
InstanceMirror propMirror = objMirror.getField(new Symbol(_name));
return propMirror.reflectee == _value;
} catch (e) {
return false;
}
}
Description describe(Description description) {
description.add("contains property \"${_name}\" with value \"${_value}\"");
}
}

Resources