Is it possible to get the whole object from debugger as Json?
There is an option View text but can I somehow View JSON?
EDIT: as noted in the comments, this is not perfect, as for some variables you will get a "stackoverflow" response
As suggested by #Mr Han's answer, here's how you can do this:
Add a new way to view objects in Intellij debugger as json by
Going to File | Settings | Build, Execution, Deployment | Debugger | Data Views | Java Type Renderers
Click + to add new renderer
Call it JSON renderer
Supply java.lang.Object for Apply renderer to objects of type
Choose Use following expression: and supply an expression like so:
if (null == this || this instanceof String)
return this;
new com.google.gson.GsonBuilder().setPrettyPrinting().create().toJson(this);
Click OK
Now when you choose Copy Value on a variable, it will copy as json.
Alternatively, as seen here, you can use the following piece of code in your debug watcher:
new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.writerWithDefaultPrettyPrinter()
.writeValueAsString( myObject )
You can try this code fragment into the Evaluate Expression(Alt + F8) on IntelliJ :
new com.fasterxml.jackson.databind.ObjectMapper() .registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule()) .disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .writerWithDefaultPrettyPrinter() .writeValueAsString( myObject );
image IntelliJ
You could use the Show as ... plugin for IntelliJ.
A small plugin to display formatted data out of the debugger and console.
Uses IntelliJ's build-in formatting capabilities.
No more need to copy values from debugger or console to a file to format them there. Following formats are supported: JSON, SQL, XML, Base64 encoded JSON, Base64 encoded text
If you have gson dependency in your project you can create a watch variable
new GsonBuilder().setPrettyPrinting().create().gson.toJson(myObject)
where myObject is your object.
Just follow it : File | Settings | Build, Execution, Deployment | Debugger | Data Views | Java Type Renderers, click + to add new render ,
copy is OK :) u can choose another jar to format it
And now , Apply, join it ~
Follow the instructions of #BradParks, and use the following expression.
For me it did not work without fully-qualified class names. I also added some modifications to the ObjectMapper. For some reason which I don't understand, even if I have Apply renderers to object of type set to java.lang.Object, I needed to typecast this as (Object)this when used as a parameter of the writeValueAsString() method.
if (this == null
|| this instanceof CharSequence
|| this instanceof Number
|| this instanceof Character
|| this instanceof Boolean
|| this instanceof Enum) {
// Here you may add more sophisticated test which types you want to exclude from the JSON conversion.
return this;
}
new com.fasterxml.jackson.databind.ObjectMapper()
.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule())
.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setVisibility(
com.fasterxml.jackson.annotation.PropertyAccessor.FIELD,
JsonAutoDetect.Visibility.ANY)
.setSerializationInclusion(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL)
.writerWithDefaultPrettyPrinter()
.writeValueAsString((Object)this);
In case someone is having hard time to make the renderers work for more complex objects - below you can find a combined JSON renderer from:
https://stackoverflow.com/a/60189764/3837638
https://stackoverflow.com/a/69802068/3837638
https://stackoverflow.com/a/63060407/3837638
The following renderer helped me to identify multiple fields with the same name in the class hierarchy, so I could change that.
Initially I was having IllegalArgumentException for serialization of a nested object that I wasn't able to analyse.
If there is an issue during serialization, with this renderer you can find the stack trace from the exception that you need to fix in the console.
Good luck!
if (null == this)
return "null";
if (this instanceof CharSequence
|| this instanceof Number
|| this instanceof Character
|| this instanceof Boolean
|| this instanceof Enum) {
// Here you may add more sophisticated test which types you want to exclude from the JSON conversion.
return this;
}
try {
String json = new GsonBuilder().setPrettyPrinting().create().toJson(this);
return json;
} catch (Exception e) {
e.printStackTrace();
}
Use Intellij plugin Debug Variable Extractor
More information -
https://plugins.jetbrains.com/plugin/16362-debug-variable-extractor
Related
I'm using xStream to some JSON. I've used xstream quite extensively over the years. However this issue has me stumped.
I'm getting the following ConversionException...
com.thoughtworks.xstream.converters.ConversionException: For input string: ".232017E.232017E44"
---- Debugging information ----
message : For input string: ".232017E.232017E44"
cause-exception : java.lang.NumberFormatException
cause-message : For input string: ".232017E.232017E44"
class : java.sql.Timestamp
required-type : java.sql.Timestamp
converter-type : com.etepstudios.xstream.XStreamTimestampConverter
line number : -1
class[1] : com.pbp.bookacall.dataobjects.AppleReceipt
converter-type[1] : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
class[2] : com.pbp.bookacall.dataobjects.AppleReceiptCollection
version : 1.4.10
-------------------------------
at com.etepstudios.xstream.XStreamTimestampConverter.unmarshal(XStreamTimestampConverter.java:87)
In my XStreamTimestampConverter class I print out the value that is attempting to be converted.. Which turns out to be the following...
XStreamTimestampConverter value = 2017-08-05 23:44:23.GMT
Here is the unmarshal function in my converter...
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context)
{
Timestamp theTimestamp;
Date theDate;
String value = reader.getValue ();
try
{
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.Z");
theDate = formatter.parse(value);
theTimestamp = new Timestamp (theDate.getTime());
}
catch (Exception e)
{
System.out.println ("XStreamTimestampConverter value = " + value);
throw new ConversionException(e.getMessage(), e);
}
return theTimestamp;
}
Any idea where this odd string is coming from? It does not exist anywhere in my JSON. Does xstream have some odd .[num]E.[num]E[num] notation for something? These numbers can change as I run this each time. Also I get an For input string: "" on occasion too. Yet the value is similar to the what is above. It's like it's randomly getting odd values for somewhere.
The data source is from Apple's In-App Purchase /VerifyReceipt web call. The system works just fine some times but then others it does not. It's also important to note that in this very case it parsed 100s of other Date/Timestamp strings using this converter. It just get's confused. Perhaps due to the size of the data?
So I figured out what was going on here. The unmarshal function above is not exactly as I have it in code...
The SimpleDateFormat formatter is actually set in the class rather than in the unmarshal method. Therefore if Xstream holds on to an instance of my converter and the unmarshal is called across multiple threads then it is possible that the formatter can get confused since it is the same object.
That's my only guess at this point as moving the formatter initialization into the method solved the issue. I would say SimpleDateFormatter is not thread safe?
It was the just the sheer about of data and the number of times it was concurrently being called that exposed this issue. Just a tip for anyone else in case this happens to them.
I'm stumped as to what may be the problem. I'm using GSON (2.2.4) to serialize/deserialize simple json objects and arrays, which I display in a JTable. Everything works fine but when I feed a json object like this:
{"1":{"336":"#1700EB","17":"#EB0000","10":"#EB0000","26":"#1700EB","3":"#1700EB","1":"#EB0000"}}
it throws this error:
com.google.gson.JsonSyntaxException: java.io.EOFException: End of input at line 1 column 71
at com.google.gson.Gson.fromJson(Gson.java:813)
at com.google.gson.Gson.fromJson(Gson.java:768)
at com.google.gson.Gson.fromJson(Gson.java:717)
When I remove the pound signs, it functions normally.
Here's the code that does the conversion:
Map<String, String> conv = null;
Type type = new TypeToken<Map<String, String>>(){}.getType();
ListMultimap<String, Object> returnMap = ArrayListMultimap.create();
try {
conv = g.fromJson(parse, type);
for(String key : conv.keySet()) {
returnMap.put("Key", key);
returnMap.put("Value", conv.get(key));
}
} catch (JsonSyntaxException jse) {
type = new TypeToken<Map<String, Object>>(){}.getType();
conv = g.fromJson(parse, type);
for(Object key : conv.keySet()) {
returnMap.put("Key", key);
returnMap.put("Value", conv.get(key));
}
}
Please note that I am working on a "legacy" application and I have little control over the values that come to the part of the code I'm working on; which is why I have that odd try-catch block.
Most users of this application are not savvy enough to treat their strings/jsons with the express purpose of avoiding tripping exceptions like the one outlined here (e.g. not including the # sign when passing it through the application; but adding it back when they need it), so I'd really like to fix it within the code.
Thanks!
Edit: I forgot to add an important detail. What I'm doing with the code is display data in tabular form. When a user selects a cell, it handles according to context. In the context of a cell containing a json object or array, it uses the code above to extract the values from the json and passes it as the new table data for the table's model. So, the sample json object should ideally come out like this (imagine table form)
336 | #1700EB
17 | #EB0000
10 | #EB0000
26 | #1700EB
3 | #1700EB
1 | #EB0000
...but it doesn't get there. The previous table that had the cell with the json object looked like this:
1 | {336=#1700EB, 17=#EB0000, 10=#EB0000, 26=#1700EB, 1=#EB0000}
Does this form have anything to do with the error? I understand that the json object form should be like this (at least the ones I work with): {"336":"#1700EB"...}. That's probably my only hunch as to what may be wrong.
Thanks for trying guys. I was able to fix the problem though, honestly, I still don't know the underlying cause. Anyway, I refactored the code to not do the initial attempt to map using Type. Apparently, it caused the problem further downstream.
Here's the amended code for the curious:
Map<String, Object> conv = null;
Type type = new TypeToken<Map<String, Object>>(){}.getType();
ListMultimap<String, Object> returnMap = ArrayListMultimap.create();
conv = g.fromJson(parse, type);
for(Object key : conv.keySet()) {
returnMap.put("Key", key);
Object check = conv.get(key.toString());
if ((check.toString().startsWith("{") && check.toString().endsWith("}")) ||
(check.toString().startsWith("[") && check.toString().endsWith("]")))
check = g.toJson(check);
returnMap.put("Value", check);
}
return returnMap;
I want to create a JSON file for use as part of a simple web prototyping exercise. LinqPAD is perfect for accessing the data from my DB in just the shape I need, however I cannot get it out as JSON very easily.
I don't really care what the schema is, because I can adapt my JavaScript to work with whatever is returned.
Is this possible?
A more fluent solution is to add the following methods to the "My Extensions" File in Linqpad:
public static String DumpJson<T>(this T obj)
{
return
obj
.ToJson()
.Dump();
}
public static String ToJson<T>(this T obj)
{
return
new System.Web.Script.Serialization.JavaScriptSerializer()
.Serialize(obj);
}
Then you can use them like this in any query you like:
Enumerable.Range(1, 10)
.Select(i =>
new
{
Index = i,
IndexTimesTen = i * 10,
})
.DumpJson();
I added "ToJson" separately so it can be used in with "Expessions".
This is not directly supported, and I have opened a feature request here. Vote for it if you would also find this useful.
A workaround for now is to do the following:
Set the language to C# Statement(s)
Add an assembly reference (press F4) to System.Web.Extensions.dll
In the same dialog, add a namespace import to System.Web.Script.Serialization
Use code like the following to dump out your query as JSON
new JavaScriptSerializer().Serialize(query).Dump();
There's a solution with Json.NET since it does indented formatting, and renders Json dates properly. Add Json.NET from NuGet, and refer to Newtonsoft.Json.dll to your “My Extensions” query and as well the following code :
public static object DumpJson(this object value, string description = null)
{
return GetJson(value).Dump(description);
}
private static object GetJson(object value)
{
object dump = value;
var strValue = value as string;
if (strValue != null)
{
var obj = JsonConvert.DeserializeObject(strValue);
dump = JsonConvert.SerializeObject(obj, Newtonsoft.Json.Formatting.Indented);
}
else
{
dump = JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.Indented);
}
return dump;
}
Use .DumpJson() as .Dump() to render the result. It's possible to override more .DumpJson() with different signatures if necessary.
As of version 4.47, LINQPad has the ability to export JSON built in. Combined with the new lprun.exe utility, it can also satisfy your needs.
http://www.linqpad.net/lprun.aspx
I'm currently having a problem with the groovy JsonBuilder: the properties of the objects I am trying to serialize are coming out in seemingly random order.
Here's the objects' class:
class Game {
String title
String gameImg2
String description
}
And this is the code I've been using:
def game = new Game(title: "a game", gameImg2: "an image", description: "desc")
def json = new JsonBuilder(game)
From this I would expect the output to be:
{"title":"a game","gameImg2":"an image", "description":"desc"}
but instead, I'm getting:
{"gameImg2":"gameImg","title":"hello","description":"desc"}.
From looking at the JsonBuilder example code, it seems that order should be maintained, and indeed, it looks like the toJson method iterates over object.properties, which is a LinkedHashMap. I would have thought this would go through the properties in the order they are declared in the class.
My best guess is that this is something to do with my initialisation of the game object - could using Map syntax to assign properties somehow, but again, this seems to create a LinkedHashMap which should preserve order.
Does anyone have an inkling of what I could have done wrong or incorrectly assumed here? Any leads would be a big help!
The problem is that you are serializing an Object to JSON. The object has declared fields that are translated to Java.
In Java it is not (easily) possible to traverse fields in the order of declaration and the JsonBuilder code definitely makes no attempt to allow this behavior.
Looking at the source code for the JsonBuilder one can see that it uses a class called JsonOutput.groovy to serialize the Object you are passing it, like so:
static String toJson(object) {
if (object == null) {
"null"
} else if (object instanceof Collection ||
object.class.isArray() ||
object instanceof Iterator ||
object instanceof Enumeration) {
"[" + object.collect { toJson(it) }.join(',') + "]"
} else if (object instanceof Enum) {
'"' + object.name() + '"'
} else {
def properties = object.properties
properties.remove('class')
properties.remove('declaringClass')
properties.remove('metaClass')
toJson(properties)
}
}
As you can see the code calls the properies member of the object which returns the object members, the order of the fields depends on the JVM and not the order of declaration.
If you want to maintain order you will need to either pass in a map representing the object or build the JSON object in order manually.
The other alternative is writing your own custom builder, which is much more complicated...
I need to encode and Decode AS3 Objects in a typed manner. http://code.google.com/p/as3corelib/ only supports untyped encoding and decoding.
http://code.google.com/p/ason/ supports some kind of typed objects but is not very robust, e.g. it fails on Date Objects. Any Recommendations ?
To make it clear: It MUST be JSON and it MUST be strong typed and robust.
JSON is built in in AS3. The preferred method to transmit data over the wire is AMF, which does provide you typed objects.
If you have to use JSON, then I guess that you might have to do with some sort of custom protocol to be able encode/decode with types.
You would actually need a reflection utility that read beans in JSON format and then produce your object. It really depends on how deep you want to go.
as3Commons has a reflect package that could help. They also have a JSONTypeProvider, which is not exactly what you need but can put you in the right tract.
You could modify any of the IOC frameworks to produce the context by parsing JSON instead of the regular XML most of them use.
You could modify ASON and add a custom type parser. You would have to send a variable in your JSON object containing the type of the object. And use that in with flash.utils.getDefinitionByName.
Another approach would be to just parse the objects with a regular JSON parser and then if it has a defined type create an instance of that objet, and initialize the properties.
Something like this, to get you started:
var beanInfo:Object = JSON.decode( jsonString );
beanInfo = _parseBean( beanInfo );
private function _parseBean(beanInfo:Object):Object{
if ( beanInfo.hasOwnProperty("_type") ) {
var clazz:Class = getDefinitionByName( beanInfo._type ) as Class;
beanInfo.__clazz = clazz;
var instance:Object = new clazz;
for( var prop:String in beanInfo ) {
if( instance.hasOwnProperty(prop) ) target[prop] = _getPropertyFrom(beanInfo[prop]);
}
}
}
private function _getPropertyFrom(property:String):* {
var xml:XML = describeType( beanInfo.__clazz );
//find the type of the current property.
var type:String = xml...
//if is a simple object then do something like
switch( type ) {
case "number":
return parseFloat(property ) as Number;
break;
case "int":
case "uint":
return parseInt( property );
break;
case "string":
return property as String;
break;
...
default
//As it is it does not suppor complex objects.
//You would use reflection. But then you could save the whole switch...
break;
}
}
Flash has its own serialization system.
var serializer:ByteArray = new ByteArray();
serializer.writeObject(new Sprite());
serializer.position = 0;
var data:String = serializer.readUTFBytes(serializer.bytesAvailable);
trace(data); //Will show you the binary jibberish
You can use registerClassAlias to add support for custom classes.
JSON doens't really define a means to convey type information. It's just strings and ints and arrays and so on. So basically you need some sort of "pickle" for AS3 that's based on JSON. I would suggest you look into Flex/Flash remoting solutions and see how they package objects to be transmitted for RPC; you might be able to modify that solution to use JSON. I'm actually doubtful you'll find a library like this. Does it have to be JSON? I'm pretty sure there are XML based libraries that do this.
JSON is not implemented in the flash virtual machine, and therefore there is no typed object "JSON" as there is "Xml." So basically you can decode JSON just fine, but the type you're going to get is Object. You can them access data using the key in the object as an associative array.
http://blog.alien109.com/2009/02/11/php5-json-as3corelib-a-beautiful-thing/
JSON lib/utils official from adobe:
http://code.google.com/p/as3corelib/source/browse/#svn%2Ftrunk%2Fsrc%2Fcom%2Fadobe%2Fserialization%2Fjson
As good as it gets. :)
There are two operations you need to consider: 1) serializing an object of a particular type into JSON and 2) deserializing a JSON string into an object of a particular type.
The serialization part is easy - just use the built-in JSON.stringify(). Deserializing a JSON string into an object of a particular type in ActionScript is where it gets interesting (and where the answer to your question is). You need to write your own deserialization function for the classe(s) you will need to deserialize. In that function, you need to provide a reviver function to JSON.parse(), which allows you to customize how the JSON gets deserialized.
For example:
public static function deserializeComplexObject(json:String):ComplexObject
{
if (null == json || "null" == json)
{
return null;
}
var complexObject:ComplexObject = new ComplexObject();
var parsedObject:Object = JSON.parse(
json,
function (key:String, value:Object):*
{
switch (key)
{
case “keyForNumber”:
return value;
case “keyForComplexObject2”:
return deserializeComplexObject2(JSON.stringify(value));
case “keyForComplexObject3”:
return deserializeComplexObject3(JSON.stringify(value));
case “keyForString”:
return value;
case “keyForBoolean”:
return value;
default:
return value;
}
}
);
complexObject.keyForNumber = parsedObject.keyForNumber;
complexObject.keyForComplexObject2 = parsedObject.keyForComplexObject2;
// continue setting fields
// …
return complexObject;
}
Each case statement corresponds to a top-level key in the JSON string. You don't actually need separate case statements for every key - you can use the default case to handle all keys that map to values that are one of the simple types (Object, Array, String, Number, Boolean, null) by returning the value as-is.
I have now forked the json part of http://code.google.com/p/as3corelib/ and added typed object support...