Gson and a comma in the last item of an array - gson

I have this JSON
{
id: 142,
fields: [
{ fieldId: 50, value: 0 },
{ fieldId: 51, value: 0 },
{ fieldId: 52, value: 0 }, // <--- Notice the comma
]
}
As you can see, there is a comma after the last item.
When I parse with GSON to these objects:
class Foo {
public int id;
public List<Field> fields;
}
class Field {
public int fieldId;
public int value;
}
using this code:
Gson gson = new Gson();
Foo foo = gson.fromJson(json, Foo.class);
I get a foo object containing 4 items in the fields array.
Is this a problem with GSON or my JSON is not a correctly formatted JSON? I thought that this last comma in JavaScript was permitted...

From RFC 8259 (Note that I am not sure if this is the latest RFC for JSON):
5. Arrays
An array structure is represented as square brackets surrounding
zero or more values (or elements). Elements are separated by
commas.
array = begin-array [ value *( value-separator value ) ] end-array
There is no requirement that the values in an array be of the same
type.
Now GSON seems to do something like interpreting the last sentence so that null is a value. So after your last comma there is a null value.
You can also test what happens if you deserialize the following:
{
id: 142,
fields: [
{ fieldId: 50, value: 0 },,,,,,
{ fieldId: 51, value: 0 },
]
}
As you might guess there will be as many null objects as there are extra commas.
I would not say that this behavior is a problem nor can I say that it is against RFC.

Related

How to use orderBy for graphQL

I am trying to sort reservesUSD of nested object dailyPoolSnapshots In descending order by timestamp and return it's first value (in other words, return the latest entry).
I know almost nothing of GraphQL and it's documentation seems confusing and scarce. Can someone help me to figure out how to sort my objects?
I am using subgraphs on the Ethereum mainnet for Curve.fi to get information about pools
My code:
pools(first: 1000) {
name
address
coins
coinDecimals
dailyPoolSnapshots(first: 1,
orderBy:{field: timestamp, order: DESC}) {
reservesUSD
timestamp
}
}
}
It throws and error:
"errors": [
{
"locations": [
{
"line": 0,
"column": 0
}
],
"message": "Invalid value provided for argument `orderBy`: Object({\"direction\": Enum(\"DESC\"), \"field\": Enum(\"timestamp\")})"
}
]
}```
Here is your solution
{
pools(first: 1000) {
name
address
coins
coinDecimals
dailyPoolSnapshots(first: 1,
orderBy: timestamp, orderDirection:desc) {
reservesUSD
timestamp
}
}
}
In the playground, you have the doc on the right, you can search dailyPoolSnapshots, if you click on it, you will have the documentation of this query
Sample for this query:
Type
[DailyPoolSnapshot!]!
Arguments
skip: Int = 0
first: Int = 100
orderBy: DailyPoolSnapshot_orderBy
orderDirection: OrderDirection
where: DailyPoolSnapshot_filter
block: Block_height
Arguments are all the params you can use
The orderBy and orderDirection are separate query params, and orderDirection needs to be lowercase for their enum syntax.
{
platforms(first: 5) {
id
pools {
id
dailyPoolSnapshots(first: 1, orderBy: timestamp, orderDirection: asc) {
timestamp
}
}
poolAddresses
latestPoolSnapshot
}
registries(first: 5) {
id
}
}

elasticsearch sort by price with currency

I have data
{
"id": 1000,
"price": "99,01USA",
},
{
"id": 1001,
"price": "100USA",
},
{
"id": 1002,
"price": "780USA",
},
{
"id": 1003,
"price": "20USA",
},
How I sort order by price (ASC , DESC)
You can alter it a little to parse price to integer and then sort it
You can create a dynamic sort function that sorts objects by their value that you pass:
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
/* next line works with strings and numbers,
* and you may want to customize it to your needs
*/
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
So you can have an array of objects like this:
var People = [
{Name: "Name", Surname: "Surname"},
{Name:"AAA", Surname:"ZZZ"},
{Name: "Name", Surname: "AAA"}
];
...and it will work when you do:
People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));
Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.
Multiple Parameters
You can use the function below to generate sort functions with multiple sort parameters.
function dynamicSortMultiple() {
/*
* save the arguments object as it will be overwritten
* note that arguments object is an array-like object
* consisting of the names of the properties to sort by
*/
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
/* try getting a different result from 0 (equal)
* as long as we have extra properties to compare
*/
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
Which would enable you to do something like this:
People.sort(dynamicSortMultiple("Name", "-Surname"));
Subclassing Array
For the lucky among us who can use ES6, which allows extending the native objects:
class MyArray extends Array {
sortBy(...args) {
return this.sort(dynamicSortMultiple(...args));
}
}
That would enable this:
MyArray.from(People).sortBy("Name", "-Surname");

Is it possible to mix Scalar and Object types in Union [duplicate]

The payload field can be Int or String scalar type.
when I write it like union type:
const schema = `
input QuickReply {
content_type: String
title: String
payload: Int | String
image_url: String
}
`
I got an error:
GraphQLError: Syntax Error GraphQL request (45:18) Expected Name, found |
44: title: String
45: payload: Int | String
^
46: image_url: String
It seems GraphQL does not support the union scalar type.
So, how can I solve this situation?
Scalars can't be used as part of unions, since per the specification, unions specifically "represent an object that could be one of a list of GraphQL Object types." Instead, you can use a custom scalar. For example:
const MAX_INT = 2147483647
const MIN_INT = -2147483648
const coerceIntString = (value) => {
if (Array.isArray(value)) {
throw new TypeError(`IntString cannot represent an array value: [${String(value)}]`)
}
if (Number.isInteger(value)) {
if (value < MIN_INT || value > MAX_INT) {
throw new TypeError(`Value is integer but outside of valid range for 32-bit signed integer: ${String(value)}`)
}
return value
}
return String(value)
}
const IntString = new GraphQLScalarType({
name: 'IntString',
serialize: coerceIntString,
parseValue: coerceIntString,
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
return coerceIntString(parseInt(ast.value, 10))
}
if (ast.kind === Kind.STRING) {
return ast.value
}
return undefined
}
})
This code effectively combines the behaviors for both the Int and String types, while still enforcing the range for 32-bit signed integers. However, you could have whatever type coercion behavior you want. Check out the source code to see how the built-in scalars work, or this article for more details around how custom scalars work.
Note that if you're trying to return one of several scalars for an output field, it's possible to utilize a union for the parent type to achieve a similar result. For example, this isn't possible:
type Post {
content: String | Int
}
but you can do the following:
type PostString {
content: String
}
type PostInt {
content: Int
}
union Post = PostString | PostInt

Enconde a list of maps in protobuf?

Background
I am trying to use protobuff for one of our apps, but I am having trouble understanding the protocol and I need help creating a .proto file.
Data
The data I need to encode is a list of maps, with the following structure:
[
{
"AwayTeam": "Osasuna",
"Date": "2017-05-07",
"Div": "SP1",
"FTAG": 1,
"FTHG": 4,
"FTR": "H",
"HTAG": 0,
"HTHG": 2,
"HTR": "H",
"HomeTeam": "Valencia",
"Season": 201617
},
{
"AwayTeam": "Osasuna",
"Date": "2016-02-27",
"Div": "SP2",
"FTAG": 1,
"FTHG": 0,
"FTR": "A",
"HTAG": 0,
"HTHG": 0,
"HTR": "D",
"HomeTeam": "Cordoba",
"Season": 201516
}
]
Each map has the following structure:
{
"AwayTeam": string, required: true
"Date": string, required: true
"Div": string, required: true
"FTAG": integer, required: true
"FTHG": integer, required: true
"FTR": string, required: true
"HTAG": integer, required: true
"HTHG": integer, required: true
"HTR": string, required: true
"HomeTeam": string, required: true
"Season": integer, required: true
}
Research
My goal is to create .proto file using proto3. So I decided to read the documentation for .proto3 files:
https://developers.google.com/protocol-buffers/docs/proto3#maps
But I was even more confused. According to the docs, I cannot have a map holding values of different types:
https://developers.google.com/protocol-buffers/docs/proto3#maps
For that I would need the equivalent of the JSON object type and check the docs for .struct.proto but that page doesn't mention anything about it.
Question
So I am rather lost here. How do I represent the mentioned data structure in a .proto?
Answer
Turns out that I don't actually need a map, a list of objects (messages) would suffice:
syntax = "proto3";
message Result {
string AwayTeam = 1;
string Date = 2;
string Div = 3;
int32 FTAG = 4;
int32 FTHG = 5;
string FTR = 6;
int32 HTAG = 7;
int32 HTHG = 8;
string HTR = 9;
string HomeTeam = 10;
int32 Season = 11;
}
message Response {
repeated Result results = 1;
}

How to check an empty JSONArray in swiftyJSON

I have a JSON that have a JSONArray as a value in one of the json inside it. here is the example of it.
[
{
"id": 1,
"symptoms" : [{\"key\":\"sample1\",\"value\":5},{\"key\":\"sample2\",\"value\":5}]
},
{
"id": 2,
"symptoms" : [{\"key\":\"sample3\",\"value\":1}]
},
{ "id": 3,
"symptoms" : []
},
{
"id": 4,
"symptoms": [{\"key\":\"sample4\",\"value\":1}]
}
]
So what I am doing is that I am parsing the inner JSON and place it in a String Array. But whenever I look up to symptoms it skips the empty JSONArray. So whenever i print the String Array it goes like this (with the given sample on top) ["sample1", "sample2", "sample3", "sample4"]. But i want to do is to append an "" to the String Array whenever the JSONArray is empty so it should be like this ["sample1", "sample2", "sample3", "", "sample4"]. Anyone can help me with this? Here is my code
var arrayHolder: [String] = []
var idHolder: [Int] = []
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = JSON(data: item["symptoms"].dataUsingEncoding(NSUTF8StringEncoding)!)
for symptoms in innerJSON.arrayValue {
arrayHolder.append(symptoms["key"].stringValue)
}
}
print(idHolder) // [1,2,3,4]
print(arrayHolder) // ["sample1","sample2","sample3","sample4"]
Just check if innerJSON is empty:
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = item["symptoms"].arrayValue // non need to create a new JSON object
if innerJSON.isEmpty {
arrayHolder.append("")
} else {
for symptoms in innerJSON {
arrayHolder.append(symptoms["key"].stringValue)
}
}
}

Resources