Return object array in Solidity - ethereum

Im trying to return an sample object from a contract but the data is always blank. Im using the BlockApps WebApi to do the work (http://blockapps.net/documentation). It always just returns a comma seperated string thats blank. Any help?
contract TrackingManager {
Hit[] hits;
function createHit(string _url, string _referrer) {
hits.push(new Hit(_url, _referrer));
}
function getHits() returns (Hit[]) {
return hits;
}
}
contract Hit {
string public url;
string public referrer;
function Hit(string _url, string _referrer) {
url = _url;
referrer = _referrer;
}
}

I may be wrong, but I think it's not possible to return struct arrays yet: http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html and https://github.com/ethereum/cpp-ethereum/issues/1788

Related

Function returning string instead of json object

I am working on/extending TOH. I have an add method that wants to push the new Hero onto the array then return user to the list.
the result of the call to addHero is coming back as a JSON hero inside double ticks, so as a string.
i have read many articles which seem to point to
angular.toJson
or
.map(response=> response.JSON())
These are not working.
Here is the excerpt from my heroes.component.ts
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.addHero({ name } as Hero)
.subscribe(hero =>
{
this.heroes.push(hero);
this.location.go('/Heroes');
}
);
}
and hero.service.ts
This clearly returns a Hero object...
addHero (hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
tap((hero: Hero) => console.log(`added hero w/ id=${hero.id}`)),
catchError(this.handleError<Hero>('addHero'))
);
}
Upon return, the result is successfully pushed to the array, but enclosed in quotes.
The UI evidence of this is that the list has a blank entry at the bottom because there is no .Name property on that final array element.
If i refresh the page, everyone gets loaded as json.
Simple question but I can not seem to find an answer. Have been through many S/O questions involving ng2, php, etc. but none seem to address ng6, or provide a clue I can take away. if they do, Im missing it.
If you want to parse a json into a javascript object you can use JSON.parse(response.JSON())
I'm guessing response.JSON() is returning the response as json, which then needs to be parsed
Edit: you can probably just remove the map => response.JSON() . As angular httpClient already parses it
The issue was the return type of the routine in the service.
#youris question got me to look harder at the service.
The issue is that the default response is not coded correctly as utf8 and 'text/html'
Here is the corrected code.
Public Function add(mh As mHero) As CustomJsonStringResult
Dim h As New TOHbos.Hero()
h.name.Value = mh.name
h.Save()
Return JsonStringResultExtension.JSONString(Me, h.JSON, HttpStatusCode.OK)
End Function
the referenced JsonStringResultExtension is credited to #NKosi in this post. (Code included for ease of referece)
Web Api: recommended way to return json string
public static class JsonStringResultExtension {
public static CustomJsonStringResult JsonString(this ApiController controller, string jsonContent, HttpStatusCode statusCode = HttpStatusCode.OK) {
var result = new CustomJsonStringResult(controller.Request, statusCode, jsonContent);
return result;
}
public class CustomJsonStringResult : IHttpActionResult {
private string json;
private HttpStatusCode statusCode;
private HttpRequestMessage request;
public CustomJsonStringResult(HttpRequestMessage httpRequestMessage, HttpStatusCode statusCode = HttpStatusCode.OK, string json = "") {
this.request = httpRequestMessage;
this.json = json;
this.statusCode = statusCode;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) {
return Task.FromResult(Execute());
}
private HttpResponseMessage Execute() {
var response = request.CreateResponse(statusCode);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
}
}
}
Making these changes, the result is json, its pushed to the array correctly, and shows up in the Heroes list correctly.

How can I test a spring-cloud-contract containing a java.time.Instant field

I want to test a contract where one field is of type java.time.Instant. But not all instances of an Instant are handled as I expect by spring-cloud-contract. Given the following simple contract:
Contract.make {
description("Get a version")
request {
method 'GET'
url '/config/version'
headers {
contentType(applicationJson())
}
}
response {
status 200
body(
nr: 42,
creationDate: producer(anyIso8601WithOffset())
)
headers {
contentType(applicationJson())
}
}
}
And this service implementation:
#RestController
public class VersionController {
#GetMapping(path = "/version")
public ResponseEntity<Version> getCurrentVersion() {
return ResponseEntity.ok(new Version(42, Instant.ofEpochMilli(0)));
}
}
Executing gradle test works fine. But if I replace the Instant with Instant.now(), my provider test fails with
java.lang.IllegalStateException: Parsed JSON [{"nr":42,"creationDate":"2018-11-11T15:28:26.958284Z"}] doesn't match the JSON path [$[?(#.['creationDate'] =~ /([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(\.\d{3})?(Z|[+-][01]\d:[0-5]\d)/)]]
which is understandable because Instant.now() produces an Instant whose string representation does indeed not match the anyIso8601WithOffset() pattern. But why is this? Why are Instants represented differently and how can I describe a contract that validates for any instant?
Ok, I found a solution that works for me. Although I do not know if this is the way to go.
In order to always get the exact same format of the serialized instant, I define the format of the corresponding property of my version bean as follows:
public class Version {
private final int nr;
private final Instant creationDate;
#JsonCreator
public Version(
#JsonProperty("nr") int nr,
#JsonProperty("creationDate") Instant creationDate)
{
this.nr = nr;
this.creationDate = creationDate;
}
public int getNr() {
return nr;
}
#JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX", timezone = "UTC")
public Instant getCreationDate() {
return creationDate;
}
}

How to parse json string in apex

i have json string like this downbelow
{"0":{"in":"mmm","loc":"1234"},"1":{"in":"mmm","loc":"1234"}}
Now i need to parse them as like
in | loc
---------
mmm| 1234
mmm| 1234
So far i did
public with sharing class Search
{
public String strTag {get;set;}
public String strlocation {get;set;}
public String result {get;set;}
public PageReference find() {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();
req.setEndpoint('http://test.3spire.net/index.php?in='+strTag+'&loc='+strlocation);
req.setMethod('GET');
//these parts of the POST you may want to customize
req.setCompressed(false);
req.setBody('key1=value1&key2=value2');
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
try {
res = http.send(req);
} catch(System.CalloutException e) {
system.debug('Callout error: '+ e);
result = ''+e;
}
Result results = (Result) JSON.deserialize(res.getBody(),ResultSet.class);
result = res.getBody();
system.debug(res.getBody());
return null;
}
public class ResultSet{
public List<Result> resultSet;
}
public class Result
{
public String ins;
public String loc;
}
}
But its returns
System.TypeException: Invalid conversion from runtime type Search.ResultSet to Search.Result
How can i solved this problem
Thanks in advance
You are calling JSON.deserialize(res.getBody(),ResultSet.class). The second parameter ResultSet is the Apex object type you want the result to be. But then you attempt to cast it to a type of Result instead.
Either do
Result results = JSON.deserialize(res.getBody(), Result.class);
or
ResultSet results = JSON.deserialize(res.getBody(), ResultSet.class);
In your case, based on the JSON it would seem you want the second option. However, your JSON doesn't quite match your ResultSet class either. Your JSON is a map, not a list. Also, there's a field mismatch between "in" and "ins". This JSON is what would match your ResultSet class:
{{"ins":"mmm","loc":"1234"},{"ins":"mmm","loc":"1234"}}

Struts2 Convert json array to java object array - not LinkedHashmap

First off my question is very similar to below however I'm not sure if the answers are applicable to my specific problem or whether I just need clarification about how to approach it:
Convert LinkedHashMap<String,String> to an object in Java
I am using struts2 json rest plugin to convert a json array into a java array. The array is sent through an ajax post request and the java receives this data. However instead of being the object type I expect it is received as a LinkedHashmap. Which is identical to the json request in structure.
[
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true},
{advance_Or_Premium=10000, available=true}
]
The data is all present and correct but just in the wrong type. Ideally I want to send the data in my object type or if this is not possible convert the LinkedHashMap from a list of keys and values into the object array. Here is the class I am using, incoming data is received in the create() method:
#Namespace(value = "/rest")
public class OptionRequestAction extends MadeAbstractAction implements ModelDriven<ArrayList<OptionRequestRest>>
{
private String id;
ArrayList<OptionRequestRest> model = new ArrayList<OptionRequestRest>();
public HttpHeaders create()
{
// TODO - need to use model here but it's a LinkedHashmap
return new DefaultHttpHeaders("create");
}
public String getId()
{
return this.id;
}
public ArrayList<OptionRequestRest> getModel()
{
return this.model;
}
public ArrayList<OptionRequestRest> getOptionRequests()
{
#SuppressWarnings("unchecked")
ArrayList<OptionRequestRest> lReturn = (ArrayList<OptionRequestRest>) this.getSession().get("optionRequest");
return lReturn;
}
// Handles /option-request GET requests
public HttpHeaders index()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("index").lastModified(new Date());
}
public void setId(String pId)
{
this.id = pId;
}
public void setModel(ArrayList<OptionRequestRest> pModel)
{
this.model = pModel;
}
// Handles /option-request/{id} GET requests
public HttpHeaders show()
{
this.model = this.getOptionRequests();
return new DefaultHttpHeaders("show").lastModified(new Date());
}
}
One of the things which is confusing me is that this code works fine and returns the correct object type if the model is not an array. Please let me know if my question is not clear enough and needs additional information. Thanks.

convert class to object actionscript 3

I`m tring to covert class to json.
The class is:
package com.globalData{
public class userSite {
private var uID:int,uName:String,uSocket:int,uZone:int,uRoom:int;
public function user(ID:int,Name:String,ZoneID:int,RoomID:int,socketID:int){
uID = ID;
uName = Name;
uSocket = socketID;
uZone = ZoneID;
uRoom = RoomID;
}
public function getName():String{
return uName;
}
public function getID():int{
return uID;
}
public function getZoneID():int{
return uZone;
}
public function getRoomID():int{
return uRoom;
}
public function getSocket():int{
return uSocket;
}
}
}
Im tryed to do:
json(Object(roomVar));
But its not work (JSOn is function on the main class)
Im need to convert the class to json and send the json -> Socket
How can i do it?
There are a few issues with your code above:
It doesn't appear as though your userSite class has a constructor. Instead, you've opted to have a user function that takes in all of the initialization arguments
You're using functions where you should probably be using accessor methods, sometimes called a getter.
public function getName():String { return uName;} would become public function get name():String { return uName;}
Instead of calling getName(), you would access name as a property: instance.name
You're attempting to pass an Object to the JSON.decode method, this method expects a String. Something like "{ 'a':1, 'b':[1,2,3] }" would be an acceptable parameter. This would return an object with two properties a and b, a would contain the value 1, and b would contain an array with the elements 1, 2, and 3. What you are looking for is actually the JSON.encode method which accepts an Object and converts it to a String (which can be parsed as JSON).
I suggest you convert all of your getXYZ() functions to accessors, this will allow an instance of that class to be read as a collection of properties, which will in turn allow the JSON.encode function to create a JSON string object from it:
package com.globalData
{
public class UserSite {
private var uID:int,uName:String,uSocket:int,uZone:int,uRoom:int;
public function UserSite(ID:int,Name:String,ZoneID:int,RoomID:int,socketID:int):void{
uID = ID;
uName = Name;
uSocket = socketID;
uZone = ZoneID;
uRoom = RoomID;
}
public function get name():String{
return uName;
}
public function get ID():int{
return uID;
}
public function get zoneID():int{
return uZone;
}
public function get roomID():int{
return uRoom;
}
public function get socket():int{
return uSocket;
}
}
}
Usage:
var roomVar:UserSite = new UserSite(1, 'Name', 2, 3, 4);
trace(JSON.encode(roomVar as Object));
Output:
{"ID":1,"name":"Name","socket":4,"roomID":3,"zoneID":2}