How to convert jsonAST.Jint to int - json

I am attempting to learn Scala, and I'm trying to parse a JSON file. I have two lines of code:
var jVal:JValue = parse(json);
val totalCount:Int = (jVal \\ "totalCount").asInstanceOf[Int];
However, (jVal \\ "totalCount") returns a JInt instead of an int. If I print it as a string, it looks like "JInt(38)".
How on earth do I convert this to a regular int? My current code throws an exception saying that
net.liftweb.json.JsonAST$JInt cannot be cast to java.lang.Integer
I've scoured the internet, but I can't find any answers. I would really prefer not to manually parse and remove the "JInt()" part of the string just to get it as an integer.
Surely I am missing a simple way to do this?

Since JInt is a case class, a convenient way to extract the value is using an extractor expression, either in a match:
myJValue match {
case JInt(x) => /* do something with x */
case JString(s) => /* do something with s */
/* etc. */
}
or just an assignment statement, when you know what type to expect:
val JInt(totalCount) = (jVal \\ "totalCount")
This will define totalCount to be the value of "totalCount" in your JSON. Note that it will be of type BigInt. If you want to, you can convert your BigInt to an Int with the toInt method. But if your number is too big for an Int, this method will give you a different number instead of an error. So if huge numbers are at all a possibility, you'll want to check first with isValidInt.
You can also get the value using the num field or values method, but in your code that's harder to work with. To use num, you'd have to do a cast of your JValue to JInt. And if you don't cast to JInt, you won't know the type of the result of values.

Related

LUA, multiple number string to number

so I use web to request json:
{"number":"1,2,3"} OR table = {number="1,2,3"}
and when I used this, it shows number:
typeof(1,2,3)
but when i directly get the data from the json/table, it shows string, so is there anyway to convert it to show it as number?
A Lua pattern might also a good choice to get the numbers from the raw string; then use tonumber() as suggested and add the numbers to a table in the sample code as shown below:
numbers = {}
str = '1,2,3'
for num in string.gmatch(str, '([^,]+)') do
table.insert(numbers, tonumber(num))
end

Indexing of elements in a Seq of string with chisel

I have, tab=Array(1.U, 6.U, 5.U, 2.U, 4.U, 3.U) and Y=Seq(b,g,g,g,b,g), tab is an array of UInt.
I want to do a map on tab as follows:
tab.map(case idx=>Y(idx))
But I keep getting the error: found chisel3.core.UInt, required Int.
I tried using the function peek() to convert idx to an Int by doing
tab.map(case idx=>Y(peek(idx).toInt)
but I get peek not found. I also saw that I cannot convert a chisel UInt to an Int here but did not understand the use of peek well with the example given. So please, is there another approach to do the above?
Thanks!
The immediate problem is that you cannot access the elements of scala collections using a hardware construct like UInt or SInt. It should work if you wrap Y in a Vec. Depending on your overall module this would probably look like
val YVec = VecInit(Y)
val mappedY = tab.map { case idx => YVec(idx) }

Setting lua table in redis

I have a lua script, which simplified is like this:
local item = {};
local id = redis.call("INCR", "counter");
item["id"] = id;
item["data"] = KEYS[1]
redis.call("SET", "item:" .. id, cjson.encode(item));
return cjson.encode(item);
KEYS[1] is a stringified json object:
JSON.stringify({name : 'some name'});
What happens is that because I'm using cjson.encode to add the item to the set, it seems to be getting stringified twice, so the result is:
{"id":20,"data":"{\"name\":\"some name\"}"}
Is there a better way to be handling this?
First, regardless your question, you're using KEYS the wrong way and your script isn't written according to the guidelines. You should not generate key names in your script (i.e. call SET with "item:" .. id as a keyname) but rather use the KEYS input array to declare any keys involved a priori.
Secondly, instead of passing the stringified string with KEYS, use the ARGV input array.
Thirdly, you can do item["data"] = json.decode(ARGV[1]) to avoid the double encoding.
Lastly, perhaps you should learn about Redis' Hash data type - it may be more suitable to your needs.

How to Conditionally Produce JSON Using JSON4S

I am using JSON4S to produce some JSON.
If a condition is met, I would like to produce the following:
{"fld1":"always", "fld2":"sometimes"}
If the condition is not met, I would like to produce:
{"fld1":"always"}
What I have tried so far is:
val fld1 = "fld1" -> "always"
val json = if(condition) ("fld2" -> "sometimes") ~ fld1 else fld1
compact(render(json))
However, this gives me a type mismatch in the render "Found: Product with Serializable. Required: org.json4s.package.JValue".
The interesting this is that render(("fld2" -> "sometimes") ~ fld1) works, and so does render(fld1). The problem seems to be with the type inferred for json.
How could I fix this?
While both of the current answers give suitable workarounds, neither explains what's going on here. The problem is that if we have two types, like this:
trait Foo
trait Bar
And an implicit conversion (or view) from one to the other:
implicit def foo2bar(foo: Foo): Bar = new Bar {}
A conditional with a Foo for its then clause and a Bar for its else clause will still be typed as the least upper bound of Foo and Bar (in this case Object, in your case Product with Serializable).
This is because the type inference system isn't going to step in and say, well, we could view that Foo as a Bar, so I'll just type the whole thing as a Bar.
This makes sense if you think about it—for example, if it were willing to handle conditionals like that, what would it do if we had implicit conversions both ways?
In your case, the then clause is typed as a JObject, and the else clause is a (String, String). We have a view from the latter to the former, but it won't be used here unless you indicate that you want the whole thing to end up as a JObject, either by explicitly declaring the type, or by using the expression in a context where it has to be a JObject.
Given all of that, the simplest workaround may just be to make sure that both clauses are appropriately typed from the beginning, by providing a type annotation like this for fld1:
val fld1: JObject = "fld1" -> "always"
Now your conditional will be appropriately typed as it is, without the type annotation.
Not the nicest way I can think of, but declaring the type yourself should work:
val json: JObject =
if(condition) ("fld2" -> "sometimes") ~ fld1 else fld1
compact(render(json))
Also, note that you can get type inference to help itself out: If you can render in one go:
compact(render(
if(condition) fld1 ~ ("fld2" -> "sometimes") else fld1
))
Another approach is to box conditional values to Options.
val json = fld1 ~ ("fld2" -> (if (condition) Some("sometimes") else None))
compact(render(json))

JPA2 Criteria API .as(String.class) casting to char(1) - How do I work around this?

Using the criteria api, I have a query which does something like:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SourcePath> pathQuery = cb.createQuery(SourcePath.class);
Root<SourcePath> pathRoot = pathQuery.from(SourcePath.class);
pathQuery.where(cb.equal(cb.literal(0x00010002).as(String.class), (pathRoot.get(SourcePath_.path))));
TypedQuery<SourcePath> query = entityManager.createQuery(pathQuery);
query.getResultList();
The resulting sql query results something like:
select ...snip aliases... from SourcePath where cast(x'00010002', char(1)) = path;
(path would be some nasty old alias, but that's irrelevant).
This query is incorrect. Particularly, the cast: cast(x'00010002', char(1)) is not a cast to as string, as specified by .as(String.class), instead it should be either cast(x'00010002', char), or cast(x'00010002', char(N) where N is a suitably big enough number.
I've isolated the cause of this cast failure to the MySqlDialect provided by org.hibernate. Particularly:
public String getCastTypeName(int code) {
if ( code==Types.INTEGER ) {
return "signed";
}
else if ( code==Types.VARCHAR ) {
return "char";
}
...snip...
}
Which farther down the chain is interpreted as a char, which is registered by the dialog: registerColumnType( Types.CHAR, "char(1)" );.
Finally, to my question. How can I work around this behaviour? Do I report it as a bug to Hibernate? Do I extend the Dialog and correct the returned type from getCastTypeName? Is there an alternative to .as which will appropriately cast? Or, should I use strings everywhere I'm currently using hex-values to avoid touching edge cases of hibernate's implementation?
Thanks
idb
IMHO, you should use a String literal like cb.literal("\u0001\u0002"). Reasons:
It's the same thing as cb.literal(0x00010002).as(String.class), but less verbose.
Does not hit any "edge case"
It's clearer: does "0x00010002" be treated in Big Endian or LE? Which encoding should be used?
You can improve legibility using constants (e.g.: cb.literal(ASCII_SOH + ASCII_STX) where SOH="\u0001" and STX="\u0002").
EDIT: Adding a better description, since I didn't see the "Or, should I use strings everywhere I'm currently using hex-values"