I want to add a BigDecimal to a list using Spring Expression Language.
public class SpelTest {
public List<BigDecimal> values;
StandardEvaluationContext context;
SpelExpressionParser parser;
#Before
public void setup() {
values = new ArrayList<>();
context = new StandardEvaluationContext(this);
parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
}
#Test
public void shouldChangeValue() {
values.add(BigDecimal.ONE);
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // passes
}
#Test
public void shouldAddValue() {
parser.parseExpression("values[0]").setValue(context, "123.4");
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4)); // fails
}
}
Changing the first entry passes but adding an entry fails with
Caused by: java.lang.NoSuchMethodException: java.math.BigDecimal.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3349)
at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
at org.springframework.util.ReflectionUtils.accessibleConstructor(ReflectionUtils.java:185)
at org.springframework.expression.spel.ast.Indexer$CollectionIndexingValueRef.growCollectionIfNecessary(Indexer.java:715)
... 55 more
Not sure why SpEL isn't able to properly initialize a BigDecimal when the list is empty. Surprisingly I found nothing about this problem.
Thanks for helping!
The problem is that you activated autoGrowCollections on the SpelParserConfiguraion.
Therefore it tries to create an element with a default constructor if you try to access a non-existing element of the collection with the index operator []. BigDecimal has no default constructor and because of this, it fails.
What you could do is to create the object in the SpEL itself. E.G.:
#Test
public void shouldAddValue() {
parser.parseExpression("values.add(0, new java.math.BigDecimal(\"123.4\"))").getValue(context);
assertThat(values.size() > 0);
assertThat(values.get(0)).isEqualTo(BigDecimal.valueOf(123.4));
}
Or you could create a subclass of BigDecimal witch has a default constructor and use this class.
You could avoid this problem by setting the whole list instead of single (not initialized) elements. Instead of
parser.parseExpression("values[0]").setValue(context, "123.4");
use:
parser.parseExpression("values").setValue(context, "123.4");
This also works for multiple elements, quite neat:
parser.parseExpression("values").setValue(context, "123.4, 456.7");
As #Nirud pointed out, the problem is, that BigDecimal does not have a default constructor. I extended SpEL to add null to the list, when there is no default constructor. See this pull request: https://github.com/spring-projects/spring-framework/pull/25367
I am trying to store an Int32[] Array and bool[] Array to Firebase but it isn't working for me. I have searched on various places, but couldn't find a solution. Can anyone tell me, how one can store an array to Firebase Real-time DB from Unity.
I am using System.Reflection to get all the public static fields of the class UserPrefs.
Here is the code, I am trying to do this job...
System.Type type = typeof(UserPrefs);
FieldInfo[] fields = type.GetFields();
foreach (var field in fields) {
if (user != null)
dbReference.Child("users").Child(user.UserId).Child(field.Name).SetValueAsync(field.GetValue(null));
else
Debug.LogError("There is no user LoggedIn to write...");
}
Above code saves all values other than arrays. Error given on arrays is following:
InvalidCastException: Cannot cast from source type to destination
type.
Firebase.Database.Internal.Utilities.Validation.ValidateWritableObject
(System.Object object)
Any help will be much appreciated...
You need a class like this.
public class MyClass
{
public int[] intArray = new int[10];
}
Then you can write that object to the Firebase like this.
public void WriteArrays()
{
MyClass temp = new MyClass();
for (int i = 0; i < temp.intArray.Length; i++)
{
temp.intArray[i] = i;
}
databaseReference.Child("MyArrayNode").SetRawJsonValueAsync(JsonUtility.ToJson(temp));
}
databaseReference is a reference to your root.
Same way you can do this for your bool[] also.
For a more general solution you can copy the JsonHelper class which was suggested here.
Example usage:
string jsonArray = JsonHelper.ToJsonArray(mySerializeableList);
var nodeToUpdate = this.dbReference.Child("wantedNode");
nodeToUpdate.SetRawJsonValueAsync(jsonArray);
Ref : Cannot reference "X" before supertype constructor has been called, where x is a final variable
class ArrayFunctions {
//public Integer[] arrayTemplate;
private static Scanner scanner = new Scanner(System.in);
ArrayFunctions(int k){
Integer[] arrayTemplate = new Integer[k] ;
}
.
.
.
public class ArrayFunctionsImplementation{
public static void main(String[] args) {
ArrayFunctions newArray = new ArrayFunctions(5);
newArray.getIntegers(newArray.arrayTemplate);
newArray.printIntegers(newArray.arrayTemplate);
newArray.sortArray(newArray.arrayTemplate);
newArray.printIntegers(newArray.arrayTemplate);
}
}
}
If I use the declaration //public Integer[] arrayTemplate; that is currently commented out , I am able to access the variable "arrayTemplate" in the public class.
But if I declare the variable by calling the constructor as per the code below, I am unable to access it anywhere. If I understand correctly, both the ways declare the variable and by the time I am trying to access it , the object is already created.
PS : I am using Integer class just for experimentation instead of using plain int
Cheers
Your current code declares a variable of the ArrayFunctions constructor and so, that variable is only accessible in your constructor.
Your commented code, declares a member of the ArrayFunctions class, which then can be accessed anywhere from the class (or elsewhere since you made it public).
I need to deserialize the next Json string that has several nested Json arrays:
{"d1":[["11791452",[["980",""]]],["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["11791454",[["1070",""]]]]}
I try to do it in several steps, so far I'm able to deserialize three levels of nested arrays. As follow:
{"aOaOa":[[["1060",""],["1140",""],["1220",""],["1300",""]]]}
public class ThreeSimpleNestedArrays
{
public List<List<string[]>> aOaOa; //array of arrays of arrays
public ThreeSimpleNestedArrays()
{
aOaOa = new List<List<string[]>>();
}
}
But the problem arise when I add the extra string in the array structure:
{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public class ComplexNestedArray
{
public List<Dictionary<string,List<string[]> >> TEST;
public ComplexNestedArray()
{
TEST = new List<Dictionary<string, List<string[]>>>();
}
}
I'm getting the next error message:
"Unable to cast object of type 'System.String' to type 'System.Collections.Generic.Dictionary`2[System.String,System.Object]'."
What am I missing?
Can anybody suggest a way to deserialize an object like this nested within Json arrays using DataContractJsonSerializer?
The code I use to deserialize is the next:
//Works
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ThreeSimpleNestedArrays));
ThreeSimpleNestedArrays root = (ThreeSimpleNestedArrays)dcJsonSer.ReadObject(str);
//Don't work
DataContractJsonSerializer dcJsonSer = new DataContractJsonSerializer(typeof(ComplexNestedArray));
ComplexNestedArray root = (ComplexNestedArray)dcJsonSer.ReadObject(str);
Btw, I'm able to deserilize the object when it is serilized as a Json Object as follow:
{"TEST": [{"s": "11791453","aOa": [["1060",""],["1140",""],["1220",""],["1300",""]]},{"s": "123456","aOa":[["0","1"],["2","3"]]}]}
using a class with two members (a string "s" and a List of string[] "aOa"), but without the names, when the object is serialized as an array, I'm unable to do it.
Any suggestion?
Ok, it looks like the DataContractJsonSerializer is smarter than I though .
It turns out that the way to deserialize that kid of nested objects array is with a class like this:
public class ComplexNestedArray
{
//{"TEST": [["11791453",[["1060",""],["1140",""],["1220",""],["1300",""]]],["123456",[["0","1"],["2","3"]]]]}
public List<List<object>> TEST { get; set; }
}
After that, it is only a mater to do a couple of for cycles and casts to the appropriate class structure.
Btw, This is a MUST in your toolbox in case you have to deal with Json:
json2csharp
Here is my solution. However I'll try to add later a way for your full json:
class Program {
static void Main(string[] args) {
new Program();
}
public Program() {
string full = "{\"d1\":[[\"11791452\",[[\"980\",\"\"]]],[\"11791453\",[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]],[\"11791454\",[[\"1070\",\"\"]]]]}";
string simple1 = "{\"aOa\":[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]}";
string simple2 = "{\"aOaOa\":[[[\"1060\",\"\"],[\"1140\",\"\"],[\"1220\",\"\"],[\"1300\",\"\"]]]}";
DataContractJsonSerializer d1 = new DataContractJsonSerializer(typeof(S1));
S1 r1 = (S1)d1.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple1)));
DataContractJsonSerializer d2 = new DataContractJsonSerializer(typeof(S2));
S2 r2 = (S2)d2.ReadObject(new MemoryStream(Encoding.Default.GetBytes(simple2)));
Console.WriteLine("done");
Console.ReadKey();
}
[DataContract]
class S1 {
[DataMember]
List<List<String>> aOa;
}
[DataContract]
class S2 {
[DataMember]
List<List<List<string>>> aOaOa;
}
}
I'm a beginner with JAX RS architecture. I've made a simple class like this:
#XmlRootElement
public class DatoBase
{
private int _id;
private String _name;
private int[] _listId;
//...here all get and set methods
}
This class, as you can see has an array (_listId), correctly initialized.
I've made my web services, that correctly istantiate and POST a new element of DatoBase, and I've made a method to GET this element, that is:
#GET
#Produces("application/json")
#Path("{id}")
public DatoBase GetDato(#PathParam("id") int dId)
{
return dati.get(dId);
}
where dati is declared as:
private TreeMap<Integer,DatoBase> dati = new TreeMap<Integer,DatoBase>();
but when I try to get the element i've already posted, i see this structure:
{"id":"0","name":"Dato10"}
I can't see my _listId structure (initialized with 3 elements) in this output.
I expected an output like this:
{"id":"0","name":"Dato10","listId":[...]}
Could anyone help me or tell me why?
Thank you
You should annotate your array with #XmlElementWrapper.
#XmlElementWrapper
private int[] _listId;
See here for further reference.