I have the following gml fragment:
<gml:LineString srsName="EPSG:25832"><gml:coordinates>663957.75944074022118,5103981.64908889029175 663955.915655555087142,5103991.151674075052142</gml:coordinates></gml:LineString>
I would like to convert it to a wkt string with the EPSG:4326 srs.
I found a hacky solution, the main isue, is that the input is just a gml fragment and not a valid document. So it is not possible to use xpath to extract the srsName attribute, because the namespaces are not bound.
I searched with a regex for the srsName attribute and transformed the geometry.
try {
String gml = "<gml:LineString srsName=\"EPSG:25832\"><gml:coordinates>663957.75944074022118,5103981.64908889029175 663955.915655555087142,5103991.151674075052142</gml:coordinates></gml:LineString>";
Geometry geometry = gmlReader.read(gml, geometryFactory);
Pattern p = Pattern.compile("srsName=\\\"([^\"]*)\\\"");
Matcher m = p.matcher(gml);
if (m.find()) {
String srs = m.group(1);
CoordinateReferenceSystem crsSource = CRS.decode(srs);
GeographicCRS crsTarget =
org.geotools.referencing.crs.DefaultGeographicCRS.WGS84;
MathTransform transform = CRS.findMathTransform(crsSource, crsTarget, false);
geometry = JTS.transform(geometry, transform);
}
String wktString = wktWriter.write(geometry);
} catch (Exception e) {
throw new RuntimeException(e);
}
Ugly as ****, is there a cleaner way?
Related
My source code of voxel terrain can't save the data. I have a 3D char array called terrain and when I save, then it's result is empty json. The result is:
{}
The source code is:
public void TerrainSave() {
LoadingSavingClass myObject = new LoadingSavingClass();
myObject.terrain = terrain;
string json = JsonUtility.ToJson(myObject);
File.WriteAllText(Application.streamingAssetsPath + "/terrain/save.ter", json);
if(json == "{}")
{
Debug.Log("Saved clear data");
}
}
The class is:
[Serializable]
public class LoadingSavingClass
{
public char[,,] terrain = new char[128, 32, 128];
}
The saved 3D char char array isn't empty, I put some data into it before saving.
As mentioned here in JSON Serialization Docs JsonUtility.ToJson will only serialize the same types as you can serialize in Unity's inspector. char[,,,] won't serialize in Unity's inspector so it won't serialize with JsonUtility.ToJson
I need a generic routine that takes any valid XML and converts it to JSON without knowing the underlying data type. I know that this is easily done with Json.Net and I also know how to do it with the DataContractJsonSerializer but our organisation doesn't use Json.Net and the DataContractJsonSerializer needs a Data Contract enabled object type.
My working code using Json.Net:
XmlDocument document = new XmlDocument();
document.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(document);
The code I'd like to be able to use, using JsonReaderWriterFactory instead of Json.Net:
string jsonText = string.Empty;
MemoryStream stream = new MemoryStream();
StreamWriter streamWriter = new StreamWriter(stream);
streamWriter.Write(xml);
streamWriter.Flush();
stream.Position = 0;
using (XmlDictionaryWriter xmlWriter = JsonReaderWriterFactory.CreateJsonWriter(stream))
{
object someObject = new object();
DataContractJsonSerializer serializer = new DataContractJsonSerializer(someObject.GetType());
serializer.WriteObject(stream, someObject);
xmlWriter.Flush();
jsonText = Encoding.Default.GetString(stream.GetBuffer());
}
Is there a way around this?
Too bad the Json.Net isn't an option - we've used it for years now, and it's fantastic. Short of native parsing and json generation by hand, there's not a lot of fast ways to do this.
Check out the code from this link:
http://www.phdcc.com/xml2json.htm (See section "XmlToJSON C# code", should be fairly quick)
This code could easily be adapted to a class or even extension to convert an XML Document (or even just xml string being parsed into an XML document, then returning the json.
Another approach to consider could be the following. It specifies using anonymous types assuming you don't have control of the objects that could be deserialized from XML (and you don't want to manage those separate types).
Convert the XML into an anonymous type (probably through the
Use the JavascriptSerializer to serialize the anonymous object into the json
The code sample below shows this techinique:
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Data.Entity.Design.PluralizationServices;
using System.Globalization;
namespace Scratch
{
class Program
{
static void Main(string[] args)
{
string xml = "<root><student><id>1</id></student><student><id>2</id></student></root>";
string json = XmlToJson(xml);
Console.WriteLine(json);
Console.ReadKey(true);
}
// Using JavaScriptSerializer
static string XmlToJson(string xml)
{
var obj = GetAnonymousType(xml);
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return serializer.Serialize(obj);
}
// Adapted from: http://www.codeproject.com/Tips/227139/Converting-XML-to-an-dynamic-object-using-ExpandoO
static dynamic GetAnonymousType(string xml, XElement node = null)
{
node = string.IsNullOrEmpty(xml) ? node : XDocument.Parse(xml).Root;
IDictionary<String, dynamic> result = new ExpandoObject();
var pluralizationService = PluralizationService.CreateService(CultureInfo.CreateSpecificCulture("en-us"));
node.Elements().AsParallel().ForAll(gn =>
{
var isCollection = gn.HasElements
&& (gn.Elements().Count() > 1
&& gn.Elements().All(e => e.Name.LocalName.ToLower() == gn.Elements().First().Name.LocalName)
|| gn.Name.LocalName.ToLower() == pluralizationService.Pluralize(gn.Elements().First().Name.LocalName).ToLower());
var items = isCollection ? gn.Elements().ToList() : new List<XElement>() { gn };
var values = new List<dynamic>();
items.AsParallel().ForAll(i => values.Add((i.HasElements) ? GetAnonymousType(null, i) : i.Value.Trim()));
result[gn.Name.LocalName] = isCollection ? values : values.FirstOrDefault();
});
return result;
}
}
}
I'd like to use the Json library that comes with the play 2.1 framework.
But I'm stuck with deserializing a json object back into a java List.
With gson, you can write s.th. like
Type type = new TypeToken<List<XYZ>>(){}.getType();
List<XYZ> xyzList = gson.fromJson(jsonXyz, type);
Is there a way to do the same with play.libs.Json.fromJson ?
Any help appreciated.
Edit (17.12.2013):
I did the following to work around the problem. I guess there is a better way, but I didn't found it.
List<MyObject> response = new ArrayList<MyObject>();
Promise<WS.Response> result = WS.url(Configuration.getRestPrefix() + "myObjects").get();
WS.Response res = result.get();
JsonNode json = res.asJson();
if (json != null) {
for (JsonNode jsonNode : json) {
if (jsonNode.isArray()) {
for (JsonNode jsonNodeInner : jsonNode) {
MyObject mobj = Json.fromJson(jsonNodeInner, MyObject.class);
response.add(bst);
}
} else {
MyObject mobj = Json.fromJson(jsonNode, MyObject.class);
response.add(bst);
}
}
}
return response;
The Json library for Play Java is really just a thin wrapper over the Jackson JSON library (http://jackson.codehaus.org/). The Jackson way to deserialize a list of custom objects is mentioned here.
For your case, once you parse the json from the response body, you would do something like this, assuming MyObject is a plain POJO:
JsonNode json = res.asJson();
try{
List<MyObject> objects = new ObjectMapper().readValue(json, new TypeReference<List<MyObject>>(){});
}catch(Exception e){
//handle exception
}
I'm assuming you were asking about Play Java based on your edit, Play Scala's JSON library is also based on Jackson but has more features and syntactic sugar to accommodate functional programming patterns.
You can use the following code:
List<YourClass> returnedRoles = new ObjectMapper().readValue(jsonString
,TypeFactory.defaultInstance().constructCollectionType(List.class,
YourClass.class));
In the project, I have to send complex JSON commands form the server to the client. Is it effective to generate JSONObjects ( Strings, Numbers, etc.) convert them to the string and then send them via RequestBuilder or is there a more effective method.
Is it effective to convert JSON objects to string (via the .toString method on the Object)
Code example:
JSONObject retObject = new JSONObject();
retObject.put("NumberVar", new JSONNumber(1));
retObject.put("StringVar", new JSONString("HelloWorld"));
JSONArray arrayVar= new JSONArray();
for (int i = 0; i < 5; i++) {
arrayVar.set(i,
new JSONString("Array"));
}
retObject.put("EventParameters", arrayVar);
System.out.println(retObject.toString());
Output:
{"NumberVar":1, "StringVar":"HelloWorld", "EventParameters":["Array","Array","Array","Array","Array"]}
Regards,
Stefan
The solution you have will work.
If you want to do it more efficiently, and you only want to support modern browsers with support for JSON.stringify(), you can work in JavaScriptObjects instead of JSONObjects and use this native method:
private static native String stringify(JavaScriptObject jso) /*-{
return JSON.stringify(jso);
}-*/;
Alternatively, you can stringify a JSO by doing:
String json = new JSONObject(jso).toString();
JavaScriptObjects are more efficient because they are represented in the final compiled code as JS objects, while JSONObjects are represented as emulated Java objects. The second solution will mean less overhead while you construct the JSO, but comparatively more (than the first) when you stringify it.
Your solution will work just fine though.
There's also AutoBeans.
public interface MyJsonFactory extends AutoBeanFactory {
AutoBean<MyJsonObj> myJsonObj();
}
public interface MyJsonObj {
#PropertyName("NumberVar")
int getNumberVar();
#PropertyName("NumberVar")
void setNumberVar(int val);
#PropertyName("StringVar")
String getStringVar();
#PropertyName("StringVar")
void setStringVar(String val);
#PropertyName("EventParameters")
List<String> getEventParameters();
#PropertyName("EventParameters")
void setEventParameters(List<String> val);
}
MyJsonFactory factory = GWT.create(MyJsonFactory.class);
AutoBean<MyJsonObj> bean = factory.myJsonObj();
MyJsonObj obj = bean.as();
// bean and obj are 2 distinct view on the exact same data
obj.setNumberVar(1);
obj.setStringVar("HelloWorld");
List<String> list = new ArrayList<String>(5);
for (int i = 0; i < 5; i++) {
list.add("Array");
}
obj.setEventParameters(list);
System.out.println(AutoBeanCodex.encode(bean).getPayload());
The #PropertyName is needed is as your JSON property names do not align with the AutoBean conventions (inspired by Java Beans ones), where getNumberVar() gets a numberVar property (with lower-case n)
I might be getting a bit tired tonight but here it goes:
I'd like to have GWT HashMap to/from JSON. How would I achieve this?
In other words, I'd like to take an HashMap, take its JSON representation, store it somewhere and get it back to its native Java representation.
Here is my quick solution:
public static String toJson(Map<String, String> map) {
String json = "";
if (map != null && !map.isEmpty()) {
JSONObject jsonObj = new JSONObject();
for (Map.Entry<String, String> entry: map.entrySet()) {
jsonObj.put(entry.getKey(), new JSONString(entry.getValue()));
}
json = jsonObj.toString();
}
return json;
}
public static Map<String, String> toMap(String jsonStr) {
Map<String, String> map = new HashMap<String, String>();
JSONValue parsed = JSONParser.parseStrict(jsonStr);
JSONObject jsonObj = parsed.isObject();
if (jsonObj != null) {
for (String key : jsonObj.keySet()) {
map.put(key, jsonObj.get(key).isString().stringValue());
}
}
return map;
}
Not the most optimized, but should be easy to code: use JSONObject.
Iterate over your map's entries and put them in a JSONObject (converting each value to a JSONValue of the appropriate type), then call toString to get the JSON representation.
For parsing, get a JSONObject back using a JSONParser, then iterate over the keySet, geting the values and putting them in your map (after unwrapping the JSONValues)
But beware of the keys you use! You cannot use any kind of key as a property name in JS; and JSON processing in the browser always involve going through a JS object (or implementing the JSON parser yourself, which won't perform the same)