while trying to test physcis body editor loader (BodyEditorLoader.java) from here
i get this improper casting, below is the function
private Model readJson(String str) {
Model m = new Model();
OrderedMap<String,?> rootElem
= (OrderedMap<String,?>) new JsonReader().parse(str); //this line has casting problem
Array<?> bodiesElems = (Array<?>) rootElem.get("rigidBodies");
for (int i=0; i<bodiesElems.size; i++) {
OrderedMap<String,?> bodyElem = (OrderedMap<String,?>) bodiesElems.get(i);
RigidBodyModel rbModel = readRigidBody(bodyElem);
m.rigidBodies.put(rbModel.name, rbModel);
}
return m;
}
as the new version of libgdx does support Jsonvalue and with this help
private Model readJson(String str) {
Model m = new Model();
JsonValue map = new JsonReader().parse(str);
JsonValue bodyElem = map.getChild("rigidBodies");
for (; bodyElem != null; bodyElem = bodyElem.next()) {
RigidBodyModel rbModel = readRigidBody(bodyElem);
m.rigidBodies.put(rbModel.name, rbModel);
}
return m;
}
The parse method returns a JsonValue.
You're probably seeing this mismatch due to a newer build of Libgdx including a not-backwards-compatible change to the JSON code. See the blog post which includes this:
Only reading JSON is affected. If you use JsonReader, you’ll get back
a JsonValue instead of an OrderedMap.
You can either fix this by updating the code to work with a JsonValue or by downgrading to an older version of libgdx (before April 25th). If you're using nightly builds of Libgdx, definitely pay attention to the CHANGES and keep up with the blog (where most of the big changes are announced). Otherwise, its probably safer to stick to the "released" versions of Libgdx.
Related
I have a JavaFX application with a lot of ToggleButtons, ComboBoxes and TextFields organised in lists by their types. I have also a JSON file with list of my Member's class objects.
Ofcourse I have a #FXML adnotations buttons for buttons, etc.
When my app launch I want to set for everyone ToggleButton a specific Text what I have prepared in JSON file for specific Member. I planned to do this by using initialize() method to call my method fillToggleButtons():
List<Member> membersFromJSON = new ArrayList<>();
List<ToggleButton> sendToTeamMembers = new ArrayList<>();
private void fillToggleButtons() {
Reader reader = null;
try {
reader = new FileReader(JSONFilePaths.membersJSONFilePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Gson gson = new Gson();
Type memberList = new TypeToken<ArrayList<Member>>() {}.getType();
List<Member> members = gson.fromJson(reader, memberList);
for (int i = 0; i < sendToTeamMembers.size(); i++) {
for (int k = 0; k < members.size(); k++) {
sendToTeamMembers.get(i).setText(members.get(k).getName());
}
}
}
But when I do this, my loops don't work. I have the same Text for everyone ToggleButton, but in JSON file I have them different. Do I need an ObservableList here instead of standard java List?
The same question for ComboBoxes (I know I should use index, also I have it in the same JSON file as Member's ID/index).
What should I do for set Text in loop for JavaFX objects?
Your loop logic is wrong - you're setting each ToggleButton's text multiple times (first to members.get(0).getName(), then to members.get(1).getName(), etc).
In the end, each ToggleButton will have its name set to the name of the last member from the list.
You only need one for loop:
for (int i = 0; i < sendToTeamMembers.size(); i++) {
sendToTeamMembers.get(i).setText(members.get(i).getName());
}
Be sure to check if members list contains at least sendToTeamMembers.size() elements before you call the code above - and if it doesn't, there's probably some error with loading/parsing your JSON file that you'll need to fix first.
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 have a ASP.NET WebApi project that I am working on. The boss would like the returns to support "partial response", meaning that though the data model might contain 50 fields, the client should be able to request specific fields for the response. The reason being that if they are implementing for example a list they simply don't need the overhead of all 50 fields, they might just want the First Name, Last Name and Id to generate the list. Thus far I have implemented a solution by using a custom Contract Resolver (DynamicContractResolver) such that when a request comes in I am peeking into it through a filter (FieldListFilter) in the OnActionExecuting method and determining if a field named "FieldList" is present and then if it is I am replacing the current ContractResolver with a new instance of my DynamicContractResolver and I pass the fieldlist to the constructor.
Some sample code
DynamicContractResolver.cs
protected override IList<JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
List<String> fieldList = ConvertFieldStringToList();
IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
if (fieldList.Count == 0)
{
return properties;
}
// If we have fields, check that FieldList is one of them.
if (!fieldList.Contains("FieldList"))
// If not then add it, FieldList must ALWAYS be a part of any non null field list.
fieldList.Add("FieldList");
if (!fieldList.Contains("Data"))
fieldList.Add("Data");
if (!fieldList.Contains("FilterText"))
fieldList.Add("FilterText");
if (!fieldList.Contains("PageNumber"))
fieldList.Add("PageNumber");
if (!fieldList.Contains("RecordsReturned"))
fieldList.Add("RecordsReturned");
if (!fieldList.Contains("RecordsFound"))
fieldList.Add("RecordsFound");
for (int ctr = properties.Count-1; ctr >= 0; ctr--)
{
foreach (string field in fieldList)
{
if (field.Trim() == properties[ctr].PropertyName)
{
goto Found;
}
}
System.Diagnostics.Debug.WriteLine("Remove Property at Index " + ctr + " Named: " + properties[ctr].PropertyName);
properties.RemoveAt(ctr);
// Exit point for the inner foreach. Nothing to do here.
Found: { }
}
return properties;
}
FieldListFilter.cs
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (!actionContext.ModelState.IsValid)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
// We need to determine if there is a FieldList property of the model that is being used.
// First get a reference to the model.
var modelObject = actionContext.ActionArguments.FirstOrDefault().Value;
string fieldList = string.Empty;
try
{
// Using reflection, attempt to get the value of the FieldList property
var fieldListTemp = modelObject.GetType().GetProperty("FieldList").GetValue(modelObject);
// If it is null then use an empty string
if (fieldListTemp != null)
{
fieldList = fieldListTemp.ToString();
}
}
catch (Exception)
{
fieldList = string.Empty;
}
// Update the global ContractResolver with the fieldList value but for efficiency only do it if they are not the same as the current ContractResolver.
if (((DynamicContractResolver)GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver).FieldList != fieldList)
{
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DynamicContractResolver(fieldList);
}
}
I can then send a request with the json content payload looking as such:
{
"FieldList":"NameFirst,NameLast,Id",
"Data":[
{
"Id":1234
},
{
"Id":1235
}
]
}
and I will receive a response like so:
{
"FieldList":"NameFirst,NameLast,Id",
"Data":[
{
"NameFirst":"Brian",
"NameLast":"Mueller",
"Id":1234
},
{
"NameFirst":"Brian",
"NameLast":"Mueller",
"Id":1235
}
]
}
I believe that using the ContractResolver might run into threading issues. If I change it for one request is it going to be valid for all requests thereafter until someone changes it on another request (seems so through testing) If that is the case, then I don't see the usefulness for my purpose.
In summary, I am looking for a way to have dynamic data models such that the output from a request is configurable by the client on a request by request basis. Google implements this in their web api and they call it "partial response" and it works great. My implementation works, to a point but I fear that it will be broken for multiple simultaneous requests.
Suggestions? Tips?
A simpler solution that may work.
Create a model class with all 50 members with nullable types.
Assign values to the requested members.
Just return the result in the normal way.
In your WebApiConfig.Register() you must set the null value handling.
config.Formatters.JsonFormatter.SerializerSettings =
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
You must not touch the configuration. You need the contract resolver on per-request basis. You can use it in your action method like this.
public class MyController : ApiController
{
public HttpResponseMessage Get()
{
var formatter = new JsonMediaTypeFormatter();
formatter.SerializerSettings.ContractResolver =
new DynamicContractResolver(new List<string>()
{"Id", "LastName"}); // you will get this from your filter
var dto = new MyDto()
{ FirstName = "Captain", LastName = "Cool", Id = 8 };
return new HttpResponseMessage()
{
Content = new ObjectContent<MyDto>(dto, formatter)
};
// What goes out is {"LastName":"Cool","Id":8}
}
}
By doing this, you are locking yourself into JSON content type for response messages but you have already made that decision by using a Json.NET specific feature. Also, note you are creating a new JsonMediaTypeFormatter. So, anything you configure to the one in the configuration such as media type mapping is not going to be available with this approach though.
I know this question is from many years ago, but if you're looking to do this with modern releases of the framework, I'd recommend nowadays to use OData services (http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/using-select-expand-and-value).
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 am experimenting with backbone javascript after seeing the Tekpub MVC3 screencasts by Rob Connery
i like his Massive database access, but as soon as it is getting a bit more complex than a video can possibly show you.
i added extra fields to my database, being datetime fields.
however, this javascript serializer, converts them into strings
public string toJson(dynamic content) {
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] { new ExpandoObjectConverter() });
var json = serializer.Serialize(content);
return json.ToString();
}
this makes a datetime from this: {19/10/2011 1:58:27} into this: "19/10/2011" (*values taken from the quickwatch window on runtime..., basicly comes down to a loss in precision and it now being a basic string.
after backbone pushes that back to the server (on a model.save() call), i try to update the model like Rob does:
[HttpPut]
public ActionResult Edit()
{
var model = SqueezeJson();
model.UpdatedAt = DateTime.Now;
_movies.Update(model, model.Id);
return CmoJSON(model);
}
for the SqueezeJson function, check his source
resulting in an error like this:
Arithmetic overflow error converting expression to data type datetime.
i kind of expected this to happen since i noticed the dates being dumped into strings, i had no idea how it would go back into a date time using massive.
has anyone worked with massive and dates, in a context like this (serializing to and from json)?
i know the problem isn't necessarily massive itself, it's the json serializiation that dumbs it down into a string with loss of data, and doesn't return it to a proper date.
but still, maybe someone has a better way of doing this...
any idea's are welcome...
I have encountered the same question with you.
You can change Serialize method in ExpandoObjectConverter like:
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
ExpandoObject expando = (ExpandoObject) obj;
if(expando!=null)
{
Dictionary<string,object> result = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> item in expando)
{
var value = item.Value ?? "";
if (value is DateTime)
result.Add(item.Key, ((DateTime) value).ToString("yyyy.MM.dd"));
else
{
result.Add(item.Key, value.ToString());
}
}
return result;
}
return new Dictionary<string, object>();
}