the Invoke() function on a MethodInfo object accepts parameters as an object[]. I want to be able to send a JSON encoded string instead. Is there any way to do this?
The code which i am basing mine of comes from this MSDN page
....
object wsvcClass = results.CompiledAssembly.CreateInstance(serviceName);
MethodInfo mi = wsvcClass.GetType().GetMethod(methodName);
//args in this case is an object[]. any way to pass a string?
return mi.Invoke(wsvcClass, args);
I am aware that Newtonsoft provides a way to deserialize strings but can it do so into an object[]? or is there another way to do this?
The method signature you are looking at takes an Object[] representing all parameters in your method. For example:
public void DoStuff(string x, string y, int b);
Could be called like this:
methodInfo.Invoke(wscvClass, new object[] { "x", "y string", 500 });
So in your case you should be able to call Invoke using:
string jsonEncodedString = "{ }"; // whatever you need to do to get this value
mi.Invoke(wsvcClass, new object[] { jsonEncodedString });
MethodInfo MSDN Link
Related
I have fact an issue related to convert string map to string json with below example
public class Demo {
public static void main(String[] args) throws JsonProcessingException {
String stringRequest = "{A=12, B=23}";
System.out.println(new Gson().toJson(stringRequest));
}
}
```
OUTPUT: "{A\u003d12, B\u003d23}"
Please you help me how can I map this to json string.
It is a bit unclear what actually is your problem but the main thing in your example is that you are serializing a String object to JSON. That is why you get such an output, it is not a presentation of a Map but a String.
However with that string you can easily create a Map which you can then serialize. Not saying there is any point on that unless you want to do some cleaning or so but anyway:
// Check first which kind of types are keys & values
// keys are always Strings and here it seems that values can be Integers
Type type = new TypeToken<Map<String, Integer>>(){}.getType();
// Create the actual map from that string
Map<String, Integer> map = getGson().fromJson(stringRequest, type);
// Serialize the map to the console (added pretty printing here)
System.out.println(new Gson().toJson(map));
and you can see:
{ "A": 12, "B": 23 }
I have a lambda function that accepts a String as an input parameter. When running the lambda function I get the following error:
Can not deserialize instance of java.lang.String out of START_OBJECT token\n
This is what my code too call it looks like:
InvokeRequest request = new InvokeRequest();
final String payload = "";
request.withFunctionName(FUNCTION_NAME).withPayload((String) null);
InvokeResult invokeResult = lambdaClient.invoke(request);
Assert.assertEquals(new String (invokeResult.getPayload().array(), "UTF-8"), "Success");
And this is what my handler looks like:
public String handleRequest(String s, Context context) {}
Now the contents of the string don't matter, it could be null it could be anything. I don't use the input. The obvious solution is to remove it, but because of an annotation generator i'm using I can't do that. I've tried a ByteBuffer input, String, empty String, JSON String {\"s\":\"s\"} but nothing seems to work. I believe I need to pass in a string (i.e no {}). But since I'm using InvokeRequest I don't believe I can do that. Any suggestions would be greatly appreciated.
It works by passing a JSON valid String.
String payload = "{ \"subject\" : \"content\"}";
request.withFunctionName(functionName)
.withPayload(payload);
At the receiving end you have to map it from Object to String again if that's what you want. Here I used Jackson ObjectMapper for this.
ObjectMapper objectMapper = new ObjectMapper();
try {
String payload = objectMapper.writeValueAsString(input);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
public enum SPHttpClient {
;
private static fun(clientInstance) {
HttpPost postRequest;
/* some processing*/
clientInstance.execute(postRequest);
// I need to mock this execute statement
}
}
Writing Junit test on private method fun,
How to invoke private method which is in ENUM type and also I need to mock clientInstance which is passed through argument of private method??
SPHttpClient spHttpClient;
final Method method = spHttpClient.getClass().getDeclaredMethod("fun", HttpClient.class);
method.setAccessible(true);
Object actual = method.invoke(spHttpClient, mockHttpClient);
I think getclass wont work for enums ??
The signature of invoke is invoke(Object obj, Object... args). obj has to be the this-Object. Since your method is static, there is no this object, you may pass null, but you must not omit it, i.e. following works:
final Method method = SpHttpClient.class.getDeclaredMethod("fun", HttpClient.class);
method.setAccessible(true);
Object actual = method.invoke(null, mockHttpClient);
Is there a way to make DataContractJsonSerializer emit the "odata.type" field required when posting an OData entity into a collection that supports multiple entity types (hierarchy per table)?
If I construct DataContractJsonSerializer with a settings object with EmitTypeInformation set to Always, it emits a "__type" field in the output, but that's not the field name needed for OData and the format of the value is wrong as well.
Is there any way to hook into the DataContractJsonSerializer pipeline to inject the desired "odata.type" field into the serialization output?
It would be such a hack to have to parse the serialization output in order to inject the field. How does WCF Data Services do it? Not using DataContractJsonSerializer is my guess.
Have you considered using Json.Net? Json.Net is much more extensible and the scenario that you have can be done using a custom resolver. sample code
class Program
{
static void Main(string[] args)
{
Console.WriteLine(
JsonConvert.SerializeObject(new Customer { Name = "Raghu" }, new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver()
}));
}
}
public class CustomContractResolver : DefaultContractResolver
{
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
JsonObjectContract objectContract = base.CreateObjectContract(objectType);
objectContract.Properties.Add(new JsonProperty
{
PropertyName = "odata.type",
PropertyType = typeof(string),
ValueProvider = new StaticValueProvider(objectType.FullName),
Readable = true
});
return objectContract;
}
private class StaticValueProvider : IValueProvider
{
private readonly object _value;
public StaticValueProvider(object value)
{
_value = value;
}
public object GetValue(object target)
{
return _value;
}
public void SetValue(object target, object value)
{
throw new NotSupportedException();
}
}
}
public class Customer
{
public string Name { get; set; }
}
I can't answer your first two questions, but for the third question, I found on the OData Team blog a link to the OData WCF Data Services V4 library open source code. Downloading that code, you will see that they perform all serialization and deserialization manually. They have 68 files in their two Json folders! And looking through the code they have comments such as:
// This is a work around, needTypeOnWire always = true for client side:
// ClientEdmModel's reflection can't know a property is open type even if it is, so here
// make client side always write 'odata.type' for enum.
So that to me kind of implies there is no easy, clean, simple, elegant way to do it.
I tried using a JavaScriptConverter, a dynamic type, and other stuff, but most of them ended up resorting to using Reflection which just made for a much more complicated solution versus just using a string manipulation approach.
I'm working on a little app and using GWT to build it.
I just tried making a request to a remote server which will return a response as JSON.
I've tried using the overlay types concept but I couldn't get it working. I've been changing the code around so its a bit off from where the Google GWT tutorials left.
JavaScriptObject json;
public JavaScriptObject executeQuery(String query) {
String url = "http://api.domain.com?client_id=xxxx&query=";
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
URL.encode(url + query));
try {
#SuppressWarnings("unused")
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// violation, etc.)
}
public void onResponseReceived(Request request,
Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
json =parseJson(response.getText());
} else {
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
return json;
}
public static native JavaScriptObject parseJson(String jsonStr) /*-{
return eval(jsonStr );
;
}-*/;
In the chrome's debugger I get umbrellaexception, unable to see the stack trace and GWT debugger dies with NoSuchMethodError... Any ideas, pointers?
You may have a look to GWT AutoBean framework.
AutoBean allow you to serialize and deserialize JSON string from and to Plain Old Java Object.
For me this framework became essential :
Code is cleaner than with JSNI objects (JavaScript Native Interface)
No dependancy with Framework not supported by Google (like RestyGWT)
You just define interfaces with getters and setters :
// Declare any bean-like interface with matching getters and setters,
// no base type is necessary
interface Person {
Address getAddress();
String getName();
void setName(String name):
void setAddress(Address a);
}
interface Address {
String getZipcode();
void setZipcode(String zipCode);
}
Later you can serialize or deserialize JSON String using a factory (See documentation) :
// (...)
String serializeToJson(Person person) {
// Retrieve the AutoBean controller
AutoBean<Person> bean = AutoBeanUtils.getAutoBean(person);
return AutoBeanCodex.encode(bean).getPayload();
}
Person deserializeFromJson(String json) {
AutoBean<Person> bean = AutoBeanCodex.decode(myFactory, Person.class, json);
return bean.as();
}
// (...)
First post on Stack Overflow (!) : I hope this help :)
Use JsonUtils#safeEval() to evaluate the JSON string instead of calling eval() directly.
More importantly, don't try to pass the result of an asynchronous call (like RequestBuilder#sendRequest() back to a caller using return - use a callback:
public void executeQuery(String query,
final AsyncCallback<JavaScriptObject> callback)
{
...
try {
builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable caught) {
callback.onFailure(caught);
}
public void onResponseReceived(Request request, Response response) {
if (Response.SC_OK == response.getStatusCode()) {
try {
callback.onSuccess(JsonUtils.safeEval(response.getText()));
} catch (IllegalArgumentException iax) {
callback.onFailure(iax);
}
} else {
// Better to use a typed exception here to indicate the specific
// cause of the failure.
callback.onFailure(new Exception("Bad return code."));
}
}
});
} catch (RequestException e) {
callback.onFailure(e);
}
}
Generally, the workflow you're describing consists of four steps:
Make the request
Receive the JSON text
Parse the JSON in JavaScript objects
Describe these JavaScript objects using an overlay type
It sounds like you've already got steps 1 and 2 working properly.
Parse the JSON
JSONParser.parseStrict will do nicely. You'll be returned a JSONValue object.
This will allow you to avoid using your custom native method and will also make sure that it prevents arbitrary code execution while parsing the JSON. If your JSON payload is trusted and you want raw speed, use JSONParser.parseLenient. In either case, you need not write your own parser method.
Let's say that you're expecting the following JSON:
{
"name": "Bob Jones",
"occupations": [
"Igloo renovations contractor",
"Cesium clock cleaner"
]
}
Since you know that the JSON describes an object, you can tell the JSONValue that you're expecting to get a JavaScriptObject.
String jsonText = makeRequestAndGetJsonText(); // assume you've already made request
JSONValue jsonValue = JSONParser.parseStrict(jsonText);
JSONObject jsonObject = jsonValue.isObject(); // assert that this is an object
if (jsonObject == null) {
// uh oh, it wasn't an object after
// do error handling here
throw new RuntimeException("JSON payload did not describe an object");
}
Describe as an overlay type
Now that you know that your JSON describes an object, you can get that object and describe it in terms of a JavaScript class. Say you have this overlay type:
class Person {
String getName() /*-{
return this.name;
}-*/;
JsArray getOccupations() /*-{
return this.occupations;
}-*/;
}
You can make your new JavaScript object conform to this Java class by doing a cast:
Person person = jsonObject.getJavaScriptObject().cast();
String name = person.getName(); // name is "Bob Jones"
Using eval is generally dangerous, and can result in all kinds of strange behavior, if the server returns invalid JSON (note, that it's necessary, that the JSON top element is an array, if you simply use eval(jsonStr)!). So I'd make the server return a very simple result like
[ "hello" ]
and see, if the error still occurs, or if you can get a better stack trace.
Note: I assume, that the server is reachable under the same URL + port + protocol as your GWT host page (otherwise, RequestBuilder wouldn't work anyway due to Same Origin Policy.)
You actually don't need to parse the JSON, you can use native JSNI objects (JavaScript Native Interface).
Here's an example I pulled from a recent project doing basically the same thing you're doing:
public class Person extends JavaScriptObject{
// Overlay types always have protected, zero argument constructors.
protected Person(){}
// JSNI methods to get stock data
public final native String getName() /*-{ return this.name; }-*/;
public final native String getOccupation() /*-{ return this.occupation; }-*/;
// Non-JSNI methods below
}
and then to retrieve it like so:
/**
* Convert the string of JSON into JavaScript object.
*
*/
private final native JsArray<Person> asArrayOfPollData(String json) /*-{
return eval(json);
}-*/;
private void retrievePeopleList(){
errorMsgLabel.setVisible(false);
String url = JSON_URL;
url = URL.encode(url);
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, url);
try{
#SuppressWarnings("unused")
Request request = builder.sendRequest(null, new RequestCallback() {
#Override
public void onResponseReceived(Request req, Response resp) {
if(resp.getStatusCode() == 200){
JsArray<Person> jsonPeople = asArrayOfPeopleData(resp.getText());
populatePeopleTable(people);
}
else{
displayError("Couldn't retrieve JSON (" + resp.getStatusText() + ")");
}
}
#Override
public void onError(Request req, Throwable arg1) {
System.out.println("couldn't retrieve JSON");
displayError("Couldn't retrieve JSON");
}
});
} catch(RequestException e) {
System.out.println("couldn't retrieve JSON");
displayError("Couldn't retrieve JSON");
}
}
So essentially you're casting the response as an array of JSON Objects. Good stuff.
More info here: http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsJSNI.html